Partilhar via


Otimize o seu XAML layout

APIs importantes

Layout é o processo de definição da estrutura visual para sua interface do usuário. O principal mecanismo para descrever o layout em XAML é por meio de painéis, que são objetos de contêiner que permitem posicionar e organizar os elementos da interface do usuário dentro deles. O layout pode ser uma parte cara de um aplicativo XAML — tanto no uso da CPU quanto na sobrecarga de memória. Aqui estão algumas etapas simples que você pode seguir para melhorar o desempenho do layout do seu aplicativo XAML.

Reduzir a estrutura do layout

O maior ganho no desempenho do layout vem da simplificação da estrutura hierárquica da árvore de elementos da interface do usuário. Os painéis existem na árvore visual, mas são elementos estruturais, não elementos que produzem pixels, como um Botão ou um Retângulo. Simplificar a árvore reduzindo o número de elementos que não produzem pixels normalmente proporciona um aumento significativo de desempenho.

Muitas UIs são implementadas através do aninhamento de painéis, o que resulta em árvores profundas e complexas de painéis e elementos. É conveniente aninhar painéis, mas em muitos casos a mesma interface pode ser conseguida com um painel único mais complexo. A utilização de um único painel proporciona um melhor desempenho.

Quando reduzir a estrutura do layout

Reduzir a estrutura do layout de forma trivial — por exemplo, reduzir um painel aninhado da sua página de nível superior — não tem um efeito percetível.

Os maiores ganhos de desempenho vêm da redução da estrutura de layout que se repete na interface do usuário, como em um ListView ou GridView. Esses elementos ItemsControl usam um DataTemplate, que define uma subárvore de elementos da interface do usuário que é repetidamente instanciada. Quando a mesma subárvore está sendo duplicada muitas vezes em seu aplicativo, quaisquer melhorias no desempenho dessa subárvore têm um efeito multiplicativo no desempenho geral do seu aplicativo.

Exemplos

Considere a seguinte interface do usuário.

Exemplo de layout de formulário

Estes exemplos mostram 3 maneiras de implementar a mesma interface do usuário. Cada opção de implementação resulta em pixels quase idênticos na tela, mas difere substancialmente nos detalhes da implementação.

Opção1: Elementos aninhados de StackPanel

Embora este seja o modelo mais simples, ele usa 5 elementos de painel e resulta em sobrecarga significativa.

  <StackPanel>
  <TextBlock Text="Options:" />
  <StackPanel Orientation="Horizontal">
      <CheckBox Content="Power User" />
      <CheckBox Content="Admin" Margin="20,0,0,0" />
  </StackPanel>
  <TextBlock Text="Basic information:" />
  <StackPanel Orientation="Horizontal">
      <TextBlock Text="Name:" Width="75" />
      <TextBox Width="200" />
  </StackPanel>
  <StackPanel Orientation="Horizontal">
      <TextBlock Text="Email:" Width="75" />
      <TextBox Width="200" />
  </StackPanel>
  <StackPanel Orientation="Horizontal">
      <TextBlock Text="Password:" Width="75" />
      <TextBox Width="200" />
  </StackPanel>
  <Button Content="Save" />
</StackPanel>

Opção 2: Um único Grid

A grelha adiciona alguma complexidade, mas usa apenas um único elemento de painel.

<Grid>
  <Grid.RowDefinitions>
      <RowDefinition Height="Auto" />
      <RowDefinition Height="Auto" />
      <RowDefinition Height="Auto" />
      <RowDefinition Height="Auto" />
      <RowDefinition Height="Auto" />
      <RowDefinition Height="Auto" />
      <RowDefinition Height="Auto" />
  </Grid.RowDefinitions>
  <Grid.ColumnDefinitions>
      <ColumnDefinition Width="Auto" />
      <ColumnDefinition Width="Auto" />
  </Grid.ColumnDefinitions>
  <TextBlock Text="Options:" Grid.ColumnSpan="2" />
  <CheckBox Content="Power User" Grid.Row="1" Grid.ColumnSpan="2" />
  <CheckBox Content="Admin" Margin="150,0,0,0" Grid.Row="1" Grid.ColumnSpan="2" />
  <TextBlock Text="Basic information:" Grid.Row="2" Grid.ColumnSpan="2" />
  <TextBlock Text="Name:" Width="75" Grid.Row="3" />
  <TextBox Width="200" Grid.Row="3" Grid.Column="1" />
  <TextBlock Text="Email:" Width="75" Grid.Row="4" />
  <TextBox Width="200" Grid.Row="4" Grid.Column="1" />
  <TextBlock Text="Password:" Width="75" Grid.Row="5" />
  <TextBox Width="200" Grid.Row="5" Grid.Column="1" />
  <Button Content="Save" Grid.Row="6" />
</Grid>

Opção 3: Um único RelativePanel:

Este único painel também é um pouco mais complexo do que usar painéis aninhados, mas pode ser mais fácil de entender e manter do que uma grelha .

<RelativePanel>
  <TextBlock Text="Options:" x:Name="Options" />
  <CheckBox Content="Power User" x:Name="PowerUser" RelativePanel.Below="Options" />
  <CheckBox Content="Admin" Margin="20,0,0,0" 
            RelativePanel.RightOf="PowerUser" RelativePanel.Below="Options" />
  <TextBlock Text="Basic information:" x:Name="BasicInformation"
           RelativePanel.Below="PowerUser" />
  <TextBlock Text="Name:" RelativePanel.AlignVerticalCenterWith="NameBox" />
  <TextBox Width="200" Margin="75,0,0,0" x:Name="NameBox"               
           RelativePanel.Below="BasicInformation" />
  <TextBlock Text="Email:"  RelativePanel.AlignVerticalCenterWith="EmailBox" />
  <TextBox Width="200" Margin="75,0,0,0" x:Name="EmailBox"
           RelativePanel.Below="NameBox" />
  <TextBlock Text="Password:" RelativePanel.AlignVerticalCenterWith="PasswordBox" />
  <TextBox Width="200" Margin="75,0,0,0" x:Name="PasswordBox"
           RelativePanel.Below="EmailBox" />
  <Button Content="Save" RelativePanel.Below="PasswordBox" />
</RelativePanel>

Como esses exemplos mostram, há muitas maneiras de alcançar a mesma interface do usuário. Você deve escolher considerando cuidadosamente todas as contrapartidas, incluindo desempenho, legibilidade e manutenibilidade.

Usar grades de célula única para interface do usuário sobreposta

Um requisito comum da interface do usuário é ter um layout em que os elementos se sobreponham. Normalmente, preenchimento, margens, alinhamentos e transformações são usados para posicionar os elementos dessa maneira. O controle XAML Grid é otimizado para melhorar o desempenho do layout para elementos que se sobrepõem.

Importante Para ver a melhoria, use uma de célula únicaGrid. Não defina RowDefinitions ou ColumnDefinitions.

Exemplos

<Grid>
    <Ellipse Fill="Red" Width="200" Height="200" />
    <TextBlock Text="Test" 
               HorizontalAlignment="Center" 
               VerticalAlignment="Center" />
</Grid>

Texto sobreposto num círculo

<Grid Width="200" BorderBrush="Black" BorderThickness="1">
    <TextBlock Text="Test1" HorizontalAlignment="Left" />
    <TextBlock Text="Test2" HorizontalAlignment="Right" />
</Grid>

Dois blocos de texto em uma grade

Usar as propriedades de borda embutidas de um painel

controles Grid, StackPanel, RelativePanel, e ContentPresenter têm propriedades de borda internas que permitem desenhar uma borda ao redor deles sem adicionar um elemento Border adicional ao seu XAML. As novas propriedades que suportam a borda embutida são: BorderBrush, BorderThickness, CornerRadiuse Padding. Cada um deles é um DependencyProperty, podendo ser utilizados com vinculações e animações. Eles foram projetados para serem um substituto completo para um elemento de fronteira separado.

Se a sua interface do utilizador tiver elementos de margem ao redor destes painéis, utilize a margem integrada, que economiza um elemento extra na estrutura de layout da sua aplicação. Como mencionado anteriormente, isso pode ser uma economia significativa, especialmente no caso de Interface de Utilizador repetida.

Exemplos

<RelativePanel BorderBrush="Red" BorderThickness="2" CornerRadius="10" Padding="12">
    <TextBox x:Name="textBox1" RelativePanel.AlignLeftWithPanel="True"/>
    <Button Content="Submit" RelativePanel.Below="textBox1"/>
</RelativePanel>

Use os eventos SizeChanged para responder a alterações de layout

A classe FrameworkElement expõe dois eventos semelhantes para lidar com alterações de layout: LayoutUpdated e SizeChanged. Você pode estar usando um desses eventos para receber notificação quando um elemento é redimensionado durante o layout. A semântica dos dois eventos é diferente, e há considerações importantes de desempenho na escolha entre eles.

Para um bom desempenho, SizeChanged é quase sempre a escolha certa. SizeChanged tem semântica intuitiva. Ele é gerado durante o layout quando o tamanho do FrameworkElement foi atualizado.

LayoutUpdated também é gerado durante o layout, mas tem semântica global — ele é gerado em cada elemento sempre que qualquer elemento é atualizado. É típico fazer apenas processamento local no manipulador de eventos, caso em que o código é executado com mais frequência do que o necessário. Use LayoutUpdated somente se precisar saber quando um elemento é reposicionado sem alterar o tamanho (o que é incomum).

Escolher entre painéis

Normalmente, o desempenho não é uma consideração ao escolher entre painéis individuais. Essa escolha geralmente é feita considerando qual painel fornece o comportamento de layout mais próximo da interface do usuário que você está implementando. Por exemplo, se você estiver escolhendo entre Grid, StackPanel e RelativePanel, você deve escolher o painel que fornece o mapeamento mais próximo do seu modelo mental da implementação.

Cada painel XAML é otimizado para um bom desempenho, e todos os painéis fornecem desempenho semelhante para uma interface do usuário semelhante.