x:Load 属性x:Load attribute

可使用 x:Load 优化启动、可视化树创建和 XAML 应用的内存使用。You can use x:Load to optimize the startup, visual tree creation, and memory usage of your XAML app. 使用 x:Load 具有与 Visibility 类似的视觉效果,有一点除外:如果未加载该元素,会释放其内存,并在内部使用一个小占位符来标记其在可视化树中的位置。Using x:Load has a similar visual effect to Visibility, except that when the element is not loaded, its memory is released and internally a small placeholder is used to mark its place in the visual tree.

可通过代码或使用 x:Bind 表达式加载和卸载具有 x:Load 特性的 UI 元素。The UI element attributed with x:Load can be loaded and unloaded via code, or using an x:Bind expression. 这对于减少偶尔出现或按一定条件出现的元素的成本非常有用。This is useful to reduce the costs of elements that are shown infrequently or conditionally. 在容器(如网格或 StackPanel)上使用 x:Load 时,会将该容器及其所有子容器作为一个组进行加载或卸载。When you use x:Load on a container such as Grid or StackPanel, the container and all of its children are loaded or unloaded as a group.

XAML 框架对延迟元素的跟踪会使每个具有 x:Load 的元素特性的内存使用量增加大约 600 字节,以供占位符使用。The tracking of deferred elements by the XAML framework adds about 600 bytes to the memory usage for each element attributed with x:Load, to account for the placeholder. 因此,有可能出现过度使用此特性而导致性能下降的情况。Therefore, it's possible to overuse this attribute to the extent that your performance actually decreases. 建议仅在需要隐藏的元素上使用该属性。We recommend that you only use it on elements that need to be hidden. 如果在容器上使用 x:Load,则仅为具有 x:Load 特性的元素支付开销。If you use x:Load on a container, then the overhead is paid only for the element with the x:Load attribute.

重要

从 Windows 10 版本 1703 (创意者更新) 开始提供 x:Load 属性。The x:Load attribute is available starting in Windows 10, version 1703 (Creators Update). 要使用 x:Load,Visual Studio 项目所面向的最低版本必须为 Windows 10 创意者更新(10.0,版本 15063)The min version targeted by your Visual Studio project must be Windows 10 Creators Update (10.0, Build 15063) in order to use x:Load.

XAML 属性使用方法XAML attribute usage

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

加载元素Loading Elements

有多种不同的方法可用于加载元素:There are several different ways to load the elements:

  • 使用 x:Bind 表达式指定加载状态。Use an x:Bind expression to specify the load state. 表达式应返回 true 以加载元素,返回 false 以卸载元素。The expression should return true to load and false to unload the element.
  • 使用在元素上定义的名称来调用 FindNameCall FindName with the name that you defined on the element.
  • 使用在元素上定义的名称来调用 GetTemplateChildCall GetTemplateChild with the name that you defined on the element.
  • VisualState 中,使用面向 x:Load 元素的 SetterStoryboard 动画。In a VisualState, use a Setter or Storyboard animation that targets the x:Load element.
  • 面向任何 Storyboard 中的未加载的元素。Target the unloaded element in any Storyboard.

注意:一旦启动元素的实例化,该元素便会在 UI 线程上进行创建,因此如果一次创建过多,则可能会导致 UI 不流畅。NOTE: Once the instantiation of an element has started, it is created on the UI thread, so it could cause the UI to stutter if too much is created at once.

以上面列出的任何方法创建了延迟元素后,会立即发生以下情况:Once a deferred element is created in any of the ways listed previously, several things happen:

  • 将引发该元素上的 Loaded 事件。The Loaded event on the element is raised.
  • 设置 x:Name 的域。The field for x:Name is set.
  • 将评估该元素上的所有 x:Bind 绑定。Any x:Bind bindings on the element are evaluated.
  • 如果已注册为接收有关某属性(包含延迟元素的属性)的属性更改通知,将引发此通知。If you have registered to receive property change notifications on the property containing the deferred element(s), the notification is raised.

卸载元素Unloading elements

卸载元素:To unload an element:

  • 使用 x:Bind 表达式指定加载状态。Use an x:Bind expression to specify the load state. 表达式应返回 true 以加载元素,返回 false 以卸载元素。The expression should return true to load and false to unload the element.
  • 在页面或用户控件中,调用 UnloadObject 并在对象引用中传递In a Page or UserControl, call UnloadObject and pass in the object reference
  • 调用 Windows.UI.Xaml.Markup.XamlMarkupHelper.UnloadObject 并在对象引用中传递Call Windows.UI.Xaml.Markup.XamlMarkupHelper.UnloadObject and pass in the object reference

卸载对象时,将在树中将其替换为占位符。When an object is unloaded, it will be replaced in the tree with a placeholder. 对象实例会保留在内存中,直至发布完所有引用为止。The object instance will remain in memory until all references have been released. 页面/用户控件上的 UnloadObject API 用于发布 codegen 保留的 x:Name 和 x:Bind 的引用。The UnloadObject API on a Page/UserControl is designed to release the references held by codegen for x:Name and x:Bind. 如果在应用代码中保留其他引用,还需要发布这些引用。If you hold additional references in app code they will also need to be released.

卸载元素时,将丢弃所有与元素相关联的状态,因此如果将 x:Load 用作 Visibility 的优化版本,那么在触发加载的事件时请确保通过绑定应用所有状态或通过代码重新应用所有状态。When an element is unloaded, all state associated with the element will be discarded, so if using x:Load as an optimized version of Visibility, then ensure all state is applied via bindings, or is re-applied by code when the Loaded event is fired.

限制Restrictions

使用 x:Load 时存在以下限制:The restrictions for using x:Load are:

  • 必须为元素定义x:Name   ,因为稍后需要有一种方法来查找元素。You must define an x:Name for the element, as there needs to be a way to find the element later.
  • 可仅在派生自 UIElementFlyoutBase 的类型上使用 x:Load。You can only use x:Load on types that derive from UIElement or FlyoutBase.
  • 无法在 PageUserControlDataTemplate 中的根元素上使用 x:Load。You cannot use x:Load on root elements in a Page, a UserControl, or a DataTemplate.
  • 无法在 ResourceDictionary 中的元素上使用 x:Load。You cannot use x:Load on elements in a ResourceDictionary.
  • 无法对载有 XamlReader.Load 的松散 XAML 使用 x:Load。You cannot use x:Load on loose XAML loaded with XamlReader.Load.
  • 移动父元素将清除所有尚未加载的元素。Moving a parent element will clear out any elements that have not been loaded.

备注Remarks

可对嵌套元素使用 x:Load,不过必须从最外层的元素中实现它们。You can use x:Load on nested elements, however they have to be realized from the outer-most element in. 如果尝试先实现子元素再实现父元素,将引发异常。 If you try to realize a child element before the parent has been realized, an exception is raised.

通常情况下,建议延迟第一帧中无法查看的元素。Typically, we recommend that you defer elements that are not viewable in the first frame.一个用于查找要延迟的候选项的准则是,查找正使用折叠的 Visibility 创建的元素。 A good guideline for finding candidates to be deferred is to look for elements that are being created with collapsed Visibility. 此外,由用户交互触发的 UI 也是用于查找可延迟的元素的好位置。Also, UI that is triggered by user interaction is a good place to look for elements that you can defer.

延迟 ListView 中的元素时请谨慎操作,因为延迟此类元素虽然会减少启动时间,但同时也可能降低平移性能,具体取决于要创建的内容。Be wary of deferring elements in a ListView, as it will decrease your startup time, but could also decrease your panning performance depending on what you're creating. 如果想要提升平移性能,请参阅 {x:Bind} 标记扩展x:Phase 特性文档。If you are looking to increase panning performance, see the {x:Bind} markup extension and x:Phase attribute documentation.

如果将 x:Phase 特性x:Load 结合使用,则在实现某个元素或元素树后,该绑定会应用至当前阶段并包括当前阶段。If the x:Phase attribute is used in conjunction with x:Load then, when an element or an element tree is realized, the bindings are applied up to and including the current phase. x:Phase 指定的阶段会影响或控制元素的加载状态。The phase specified for x:Phase does affect or control the loading state of the element. 当作为平移操作的一部分来回收某个列表项时,实现的元素的行为方式与其他活动元素相同,并使用相同的规则处理已编译的绑定({x:Bind} 绑定),包括分段。When a list item is recycled as part of panning, realized elements will behave in the same way as other active elements, and compiled bindings ({x:Bind} bindings) are processed using the same rules, including phasing.

一般原则是在操作前和操作后测量应用性能,以确保获得所需性能。A general guideline is to measure the performance of your app before and after to make sure you are getting the performance that you want.

示例Example

<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);
}