Атрибут x:Load

Вы можете использовать x:Load для оптимизации запуска, создания визуального дерева и использования памяти приложения XAML. Использование x:Load имеет аналогичный визуальный эффект к Видимости, за исключением того, что при загрузке элемента его память освобождается и внутренне небольшой заполнитель используется для пометки его места в визуальном дереве.

Элемент пользовательского интерфейса, атрибут x:Load, можно загрузить и выгрузить с помощью кода или с помощью выражения x:Bind . Это полезно для уменьшения затрат на элементы, которые отображаются редко или условно. При использовании x:Load в контейнере, например Grid или StackPanel, контейнер и все его дочерние элементы загружаются или выгружаются в виде группы.

Отслеживание отложенных элементов платформой XAML добавляет около 600 байт к использованию памяти для каждого элемента, атрибута x:Load, для учета заполнителя. Таким образом, можно перепользовать этот атрибут в той степени, в которой производительность на самом деле уменьшается. Рекомендуется использовать его только для элементов, которые должны быть скрыты. Если вы используете x:Load в контейнере, то затраты оплачиваются только для элемента с атрибутом x:Load.

Внимание

Атрибут x:Load доступен начиная с Windows 10 версии 1703 (Creators Update). Для использования атрибута x:Load минимальной версией, указанной в вашем проекте Visual Studio, должна быть Windows 10 Creators Update (10.0, сборка 15063).

Использование атрибутов 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 используйте анимацию Setter или Storyboard, предназначенную для элемента x:Load.
  • Нацелим на выгруженный элемент в любой раскадровки.

ПРИМЕЧАНИЕ. После запуска экземпляра элемента он создается в потоке пользовательского интерфейса, поэтому пользовательский интерфейс может заглушиться, если слишком много создается одновременно.

После создания отложенного элемента в любом из перечисленных ранее способов происходит несколько действий.

  • Вызывается событие Loaded в элементе.
  • Поле для x:Name задано.
  • Вычисляются все привязки x:Bind в элементе.
  • Если вы зарегистрировали для получения уведомлений об изменении свойств для свойства, содержащего отложенные элементы, создается уведомление.

Выгрузка элементов

Чтобы выгрузить элемент:

  • Используйте выражение x:Bind, чтобы указать состояние загрузки. Выражение должно возвращать значение true для загрузки и false , чтобы выгрузить элемент.
  • В page или UserControl вызовите ВыгрузкуObject и передайте ссылку на объект
  • Вызовите Windows.UI.Xaml.Markup.XamlMarkupHelper.UnloadObject и передайте ссылку на объект

Когда объект выгружается, он будет заменен в дереве заполнителем. Экземпляр объекта останется в памяти до тех пор, пока не будут выпущены все ссылки. API UnloadObject на странице или UserControl предназначен для выпуска ссылок, содержащихся в кодегене x:Name и x:Bind. Если вы храните дополнительные ссылки в коде приложения, они также должны быть выпущены.

При выгрузке элемента все состояние, связанное с элементом, будет удалено, поэтому при использовании x:Load в качестве оптимизированной версии видимости все состояние применяется через привязки или повторно применяется кодом при запуске события Loaded.

Ограничения

Ограничения для использования x:Load :

  • Необходимо определить x:Name для элемента, так как его необходимо найти позже.
  • Вы можете использовать только типы x:Load, производные от UIElement или FlyoutBase.
  • Нельзя использовать x:Load on root elements in a Page, UserControl или DataTemplate.
  • Нельзя использовать x:Load для элементов в ResourceDictionary.
  • Нельзя использовать x:Load на свободном языке XAML, загруженном с помощью XamlReader.Load.
  • Перемещение родительского элемента очищает все элементы, которые не были загружены.

Замечания

Вы можете использовать x:Load для вложенных элементов, однако их необходимо реализовать из внешнего элемента.  Если вы пытаетесь реализовать дочерний элемент перед реализацией родительского элемента, создается исключение.

Как правило, рекомендуется отложить элементы, которые недоступны для просмотра в первом кадре. Хорошее руководство по поиску кандидатов, которые должны быть отложены, заключается в поиске элементов, создаваемых с свернутой видимостью. Кроме того, пользовательский интерфейс, активируемый взаимодействием с пользователем, является хорошим местом для поиска элементов, которые можно отложить.

Будьте осторожны с отсрочкой элементов в ListView, так как это уменьшит время запуска, но также может снизить производительность сдвига в зависимости от того, что вы создаете. Если вы хотите увеличить производительность сдвига, ознакомьтесь с расширением разметки {x:Bind} и документацией по атрибутам x:Phase.

Если атрибут x:Phase используется в сочетании с x:Load, то при реализации элемента или дерева элементов привязки применяются вплоть до текущего этапа. Этап, указанный для x:Phase , влияет на состояние загрузки элемента или управляет ими. При перезапуске элемента списка в рамках сдвига реализованные элементы будут вести себя так же, как и другие активные элементы, а скомпилированные привязки ({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);
}