Partilhar via


atributo x:Load

Você pode usar x:Load para otimizar a inicialização, a criação de árvore visual e o uso de memória do seu aplicativo XAML. O uso de x:Load tem um efeito visual semelhante ao Visibility, exceto que, quando o elemento não é carregado, sua memória é liberada e internamente um pequeno espaço reservado é usado para marcar seu lugar na árvore visual.

O elemento da interface do usuário atribuído a x:Load pode ser carregado e descarregado via código ou usando uma expressão x:Bind . Isso é útil para reduzir os custos de elementos que são mostrados com pouca frequência ou condicionalmente. Quando se utiliza x:Load num contentor como Grid ou StackPanel, o contentor e todos os seus elementos são carregados ou descarregados como um grupo.

O rastreamento de elementos adiados pela estrutura XAML adiciona cerca de 600 bytes ao uso de memória para cada elemento atribuído a x:Load, para contabilizar o espaço reservado. Portanto, é possível usar demais esse atributo na medida em que seu desempenho realmente diminui. Recomendamos que você o use apenas em elementos que precisam ser ocultos. Se você usar x:Load em um contêiner, a sobrecarga será paga apenas pelo elemento com o atributo x:Load.

Importante

O atributo x:Load está disponível a partir do Windows 10, versão 1703 (Creators Update). A versão mínima alvo pelo seu projeto do Visual Studio deve ser o Windows 10 Creators Update (10.0, Build 15063) para usar x:Load.

Uso de atributos XAML

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

Carregando elementos

Há várias maneiras diferentes de carregar os elementos:

  • Use uma expressão x:Bind para especificar o estado de carga. A expressão deve retornar true para carregar e false para descarregar o elemento.
  • Chame FindName com o nome que você definiu no elemento .
  • Chame GetTemplateChild com o nome que você definiu no elemento .
  • Em um VisualState, use uma animação Setter ou Storyboard direcionada ao elemento x:Load.
  • Direcione o elemento não carregado em qualquer Storyboard.

Observação

Depois que a instanciação de um elemento é iniciada, ela é criada no thread da interface do usuário, portanto, pode fazer com que a interface do usuário fique paralisada se muita coisa for criada de uma só vez.

Uma vez que um elemento adiado é criado de qualquer uma das maneiras listadas anteriormente, várias coisas acontecem:

  • O evento Loaded no elemento é acionado.
  • O campo para x:Name está definido.
  • Todas as ligações x:Bind no elemento são aplicadas.
  • Se você se registrou para receber notificações de alteração de propriedade na propriedade que contém o(s) elemento(s) diferido(s), a notificação será gerada.

Descarga de elementos

Para descarregar um elemento:

  • Use uma expressão x:Bind para especificar o estado de carga. A expressão deve retornar true para carregar e false para descarregar o elemento.
  • Em um Page ou UserControl, chame UnloadObject e passe a referência de objeto
  • Chame Microsoft.UI.Xaml.Markup.XamlMarkupHelper.UnloadObject e passe a referência do objeto

Quando um objeto é removido, ele será substituído na árvore por um marcador. A instância do objeto permanecerá na memória até que todas as referências tenham sido liberadas. A API UnloadObject em uma Page/UserControl foi projetada para liberar as referências mantidas pelo codegen para x:Name e x:Bind. Se você tiver referências adicionais no código do aplicativo, elas também precisarão ser liberadas.

Quando um elemento é descarregado, todo o estado associado ao elemento será descartado, portanto, se estiver usando x:Load como uma versão otimizada de Visibility, certifique-se de que todo o estado seja aplicado por meio de associações ou seja reaplicado por código quando o evento Loaded for acionado.

Restrições

As restrições para usar x:Load são:

  • Você deve definir um x:Name para o elemento, pois precisa haver uma maneira de encontrar o elemento mais tarde.
  • Você só pode usar x:Load em tipos que derivam de UIElement ou FlyoutBase.
  • Não é possível usar x:Load em elementos raiz em uma Page, um UserControl ou um DataTemplate.
  • Não é possível usar x:Load em elementos em um ResourceDictionary.
  • Não é possível usar x:Load em XAML solto carregado com XamlReader.Load.
  • Mover um elemento pai limpará todos os elementos que não foram carregados.

Observações

Você pode usar x:Load em elementos aninhados, no entanto, eles precisam ser instanciados a partir do elemento mais externo.  Se tentar instanciar um elemento filho antes que o elemento pai tenha sido instanciado, será gerada uma exceção.

Normalmente, recomendamos que se adie a renderização de elementos que não são visíveis no primeiro quadro. Uma boa diretriz para encontrar candidatos a serem adiados é procurar elementos que estão sendo criados com Visibilidade recolhida. Além disso, a interface do usuário que é acionada pela interação do usuário é um bom lugar para procurar elementos que você pode adiar.

Tenha cuidado com adiar elementos numa ListView, pois isso diminuirá o tempo de arranque, mas também poderá diminuir o desempenho durante a navegação, dependendo do que está a criar. Se estiveres à procura de melhorar o desempenho de panorâmica, consulta a extensão de marcação {x:Bind} e a documentação do atributo x:Phase.

Se o atributo x:Phase for usado em conjunto com x:Load , então, quando um elemento ou uma árvore de elementos for realizada, as ligações serão aplicadas até e incluindo a fase atual. A fase especificada para x:Phase afeta ou controla o estado de carregamento do elemento. Quando um item de lista é reciclado como parte do movimento panorâmico, os elementos realizados se comportarão da mesma maneira que outros elementos ativos, e as ligações compiladas ({x:Bind} bindings) são processadas usando as mesmas regras, incluindo o faseamento.

Uma diretriz geral é medir o desempenho do seu aplicativo antes e depois para garantir que você esteja obtendo o desempenho desejado.

Para minimizar as alterações no comportamento (além do desempenho) ao adicionar x:Load a um elemento, as ligações x:Bind são calculadas em seus horários normais, como se nenhum elemento usasse x:Load. Por exemplo, as ligações OneTime x:Bind são calculadas quando o elemento raiz é carregado. Se o elemento não estiver disponível no momento em que a ligação x:Bind for calculada, o valor calculado será guardado e aplicado ao elemento quando ele for carregado. Esse comportamento pode ser surpreendente se você esperava que as ligações x:Bind fossem calculadas quando o elemento é realizado.

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