共用方式為


x:Load 屬性

您可以使用 x:Load 來最佳化 XAML 應用程式的啟動、視覺化樹狀結構建立和記憶體使用量。 使用 x:Load 具有與 Visibility 類似的視覺效果,只不過當元素未載入時,其記憶體將被釋放,並且內部使用小預留位置來標記其在視覺化樹狀結構中的位置。

使用 x:Load 屬性的 UI 元素可以透過程式碼載入和卸載,或使用 x:Bind 運算式。 這對於降低不常或有條件地顯示的元素成本很有用。 當您在 Grid 或 StackPanel 等容器上使用 x:Load 時,容器及其所有下層都會以群組的形式載入或卸載。

XAML 架構的延遲元素追蹤會將大約 600 個位元組新增至以 x:Load 屬性設定的每個元素的記憶體使用量,以考慮預留位置。 因此,過度使用此屬性可能會導致您的效能實際下降。 我們建議您只在需要隱藏的元素上使用它。 如果您在容器上使用 x:Load,則只會針對具有 x:Load 屬性的元素支付額外負荷。

重要

x:Load 屬性從 Windows 10 版本 1703 (Creators Update) 開始可用。 Visual Studio 專案設為目標的版本必須至少是 Windows 10 Creators Update (10.0,組建 15063),才能使用 x:Load。

XAML 屬性用法

<object x:Load="True" .../>
<object x:Load="False" .../>
<object x:Load="{x:Bind Path.to.a.boolean, Mode=OneWay}" .../>

載入元素

有幾種不同的方式來載入元素:

  • 使用 x:Bind 運算式來指定載入狀態。 運算式應該傳回 true 以載入和傳回 false 來卸載元素。
  • 使用您在元素上定義的名稱呼叫 FindName
  • 使用您在元素上定義的名稱呼叫 GetTemplateChild
  • VisualState 中,使用針對 x:Load 元素的 SetterStoryboard 動畫。
  • 將任何分鏡腳本中的卸載元素做為目標。

注意:一旦元素的具現化啟動,就會在 UI 執行緒上建立它,因此,如果一次建立太多,它可能會導致 UI 變得卡頓。

一旦以先前所列的任何方式建立延遲元素,就會發生數件事:

  • 引發元素上的已載入事件。
  • 已設定 x:Name 的欄位。
  • 套用元素上的任何 x:Bind 系結。
  • 如果您已註冊以在包含延遲元素的屬性上接收屬性變更通知,則會引發通知。

卸載元素

若要卸載元素:

  • 使用 x:Bind 運算式來指定載入狀態。 運算式應該傳回 true 以載入和傳回 false 來卸載元素。
  • 在 Page 或 UserControl 中,呼叫 UnloadObject 並傳入物件參考
  • 呼叫 Windows.UI.Xaml.Markup.XamlMarkupHelper.UnloadObject 並傳入物件參考

卸載物件時,它會在樹狀結構中取代為預留位置。 物件執行個體會保留在記憶體中,直到釋放所有參考為止。 Page/UserControl 上的 UnloadObject API 旨在釋放 codegen 所保留的 x:Name 和 x:Bind 參考。 如果您在應用程式程式碼中保留其他參考,則也需要釋放這些參考。

卸載元素時,將會捨棄與元素相關聯的所有狀態,因此如果使用 x:Load 做為 Visibility 的最佳化版本,則請確定所有狀態都是透過繫結套用,或在引發 Loaded 事件時由程式碼重新套用。

限制

使用 x:Load 的限制是:

  • 您必須為該元素定義一個 x:Name,因為稍後需要有一種方法來尋找該元素。
  • 您只能在從 UIElementFlyoutBase 衍生的類型上使用 x:Load。
  • 您不能在 PageUserControlDataTemplate 中的根元素上使用 x:Load。
  • 您無法在 ResourceDictionary 中的元素上使用 x:Load。
  • 您無法在以 XamlReader.Load 載入的鬆散 XAML 上使用 x:Load。
  • 移動上層元素將會清除任何尚未載入的元素。

備註

您可以在巢狀元素上使用 x:Load,但是它們必須從最外層元素中實作。  如果您嘗試在上層元素實現之前實現下層元素,則會引發例外狀況。

一般而言,建議您延遲無法在第一個畫面中檢視的元素。 尋找要推遲的候選項目的一個很好的指導方針,是尋找使用折疊可見度建立的元素。 此外,使用者互動所觸發的 UI 是尋找您可以延遲之元素的好位置。

請小心延遲 ListView 中的元素,因為它會減少啟動時間,但也可能降低平移效能,這取決於您所建立的內容。 如果您希望提高平移效能,請參閱 {x:Bind} 標記延伸x:Phase 屬性文件。

如果 x:Phase 屬性x:Load 結合使用,那麼當實作元素或元素樹狀結構時,繫結將會套用到目前階段 (包括目前階段)。 為 x:Phase 指定的階段確實會影響或控制元素的載入狀態。 當清單項目做為平移的一部分被回收時,已實現的元素將以與其他使用中元素相同的方式運作,並且已編譯的繫結 ({x:Bind} 繫結) 將使用相同的規則 (包括分階段) 進行處理。

一般指導方針是測量您應用程式前後的效能,以確保您取得所需的效能。

若要將 x:Load 新增至專案時的行為變更降到最低,x:Bind 系結會在正常時間計算,就像沒有使用 x:Load 的項目一樣。 例如,當根元素載入時,會計算 OneTime x:Bind 系結。 如果在計算 x:Bind 系結時未實現專案,則會在載入時儲存匯出值並套用至專案。 如果您預期 元素實現時要計算 x:Bind 系結,此行為可能會出人意料。

範例

<StackPanel>
    <Grid x:Name="DeferredGrid" x:Load="False">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>

        <Rectangle Height="100" Width="100" Fill="Orange" Margin="0,0,4,4"/>
        <Rectangle Height="100" Width="100" Fill="Green" Grid.Column="1" Margin="4,0,0,4"/>
        <Rectangle Height="100" Width="100" Fill="Blue" Grid.Row="1" Margin="0,4,4,0"/>
        <Rectangle Height="100" Width="100" Fill="Gold" Grid.Row="1" Grid.Column="1" Margin="4,4,0,0"
                   x:Name="one" x:Load="{x:Bind (x:Boolean)CheckBox1.IsChecked, Mode=OneWay}"/>
        <Rectangle Height="100" Width="100" Fill="Silver" Grid.Row="1" Grid.Column="1" Margin="4,4,0,0"
                   x:Name="two" x:Load="{x:Bind Not(CheckBox1.IsChecked), Mode=OneWay}"/>
    </Grid>

    <Button Content="Load elements" Click="LoadElements_Click"/>
    <Button Content="Unload elements" Click="UnloadElements_Click"/>
    <CheckBox x:Name="CheckBox1" Content="Swap Elements" />
</StackPanel>
// This is used by the bindings between the rectangles and check box.
private bool Not(bool? value) { return !(value==true); }

private void LoadElements_Click(object sender, RoutedEventArgs e)
{
    // This will load the deferred grid, but not the nested
    // rectangles that have x:Load attributes.
    this.FindName("DeferredGrid"); 
}

private void UnloadElements_Click(object sender, RoutedEventArgs e)
{
     // This will unload the grid and all its child elements.
     this.UnloadObject(DeferredGrid);
}