Otimizar seu layout XAMLOptimize your XAML layout

APIs importantesImportant APIs

O layout é o processo de definição da estrutura visual para sua interface do usuário.Layout is the process of defining the visual structure for your UI. O mecanismo principal 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 de interface do usuário dentro deles.The primary mechanism for describing layout in XAML is through panels, which are container objects that enable you to position and arrange the UI elements within them. O layout pode ser uma parte cara de um aplicativo XAML, tanto no uso de CPU quanto na sobrecarga de memória.Layout can be an expensive part of a XAML app—both in CPU usage and memory overhead. Aqui estão algumas etapas simples que você pode seguir para melhorar o desempenho de layout do seu aplicativo XAML.Here are some simple steps you can take to improve the layout performance of your XAML app.

Reduzir a estrutura de layoutReduce layout structure

O maior ganho no desempenho de layout vem de simplificar a estrutura hierárquica da árvore de elementos de interface do usuário.The biggest gain in layout performance comes from simplifying the hierarchical structure of the tree of UI elements. Os painéis existem na árvore visual, mas são elementos estruturais, não elementos produtores de pixels, como um Botão ou um Retângulo.Panels exist in the visual tree, but they are structural elements, not pixel producing elements like a Button or a Rectangle. Simplificar a árvore reduzindo a quantidade de elementos não produtores de pixels costuma provocar uma grande melhora no desempenho.Simplifying the tree by reducing the number of non-pixel-producing elements typically provides a significant performance increase.

Muitas interfaces do usuário são implementadas aninhando-se painéis, o que resulta em árvores profundas e complexas de painéis e elementos.Many UIs are implemented by nesting panels which results in deep, complex trees of panels and elements. É prático aninhar painéis, mas em muitos casos, a mesma interface do usuário pode ser obtida com um painel único mais complexo.It is convenient to nest panels, but in many cases the same UI can be achieved with a more complex single panel. Usar um único painel proporciona melhor desempenho.Using a single panel provides better performance.

Quando reduzir a estrutura do layoutWhen to reduce layout structure

Reduzir a estrutura do layout de maneira trivial, por exemplo, reduzindo um painel aninhado de sua página de nível superior, não possui efeitos notáveis.Reducing layout structure in a trivial way—for example, reducing one nested panel from your top-level page—does not have a noticeable effect.

Os maiores ganhos de desempenho vêm da redução de estrutura de layout que é repetida na interface do usuário, como em ListView ou GridView.The largest performance gains come from reducing layout structure that's repeated in the UI, like in a ListView or GridView. Esses elementos ItemsControl usam um DataTemplate, que define uma subárvore de elementos de interface do usuário que é instanciada muitas vezes.These ItemsControl elements use a DataTemplate, which defines a subtree of UI elements that is instantiated many times. Quando a mesma subárvore está sendo duplicada muitas vezes em seu aplicativo, qualquer melhoria no desempenho dessa subárvore tem um efeito multiplicativo sobre o desempenho geral do seu aplicativo.When the same subtree is being duplicated many times in your app, any improvements to the performance of that subtree has a multiplicative effect on the overall performance of your app.

ExemplosExamples

Considere a interface do usuário a seguir.Consider the following UI.

Exemplo de layout de formulário

Estes exemplos mostram três formas de implementar a mesma interface do usuário.These examples shows 3 ways of implementing the same UI. Cada opção de implementação resulta em pixels quase idênticos na tela, mas difere substancialmente nos detalhes de implementação.Each implementation choice results in nearly identical pixels on the screen, but differs substantially in the implementation details.

Opção 1: Elementos StackPanel aninhadosOption1: Nested StackPanel elements

Embora esse seja o modelo mais simples, ele usa 5 elementos do painel e resulta em uma sobrecarga significativa.Although this is the simplest model, it uses 5 panel elements and results in significant overhead.

  <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 GridOption 2: A single Grid

O Grid adiciona certa complexidade, mas usa apenas um único elemento do painel.The Grid adds some complexity, but uses only a single panel element.

<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:Option 3: A single RelativePanel:

Esse painel único também é um pouco mais complexo do que a utilização de painéis aninhados, mas pode ser mais fácil de entender e manter do que um Grid.This single panel is also a bit more complex than using nested panels, but may be easier to understand and maintain than a Grid.

<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 atingir a mesma interface do usuário.As these examples show, there are many ways of achieving the same UI. Você deve escolher com cuidado considerando todas as vantagens e desvantagens, inclusive o desempenho, a legibilidade e a capacidade de manutenção.You should choose by carefully considering all the tradeoffs, including performance, readability, and maintainability.

Usar grades de célula única na sobreposição de interface do usuárioUse single-cell grids for overlapping UI

Um requisito da interface do usuário comum é ter um layout em que elementos se sobrepõem uns aos outros.A common UI requirement is to have a layout where elements overlap each other. Geralmente, preenchimento, margens, alinhamentos e transformações são usados para posicionar os elementos dessa maneira.Typically padding, margins, alignments, and transforms are used to position the elements this way. O controle Grid XAML é otimizado para melhorar o desempenho do layout para elementos que se sobrepõem.The XAML Grid control is optimized to improve layout performance for elements that overlap.

Importante  Para ver a melhora, use um Grid de célula única.Important  To see the improvement, use a single-cell Grid. Não defina RowDefinitions ou ColumnDefinitions.Do not define RowDefinitions or ColumnDefinitions.

ExemplosExamples

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

Texto sobreposto em um 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

Use as propriedades de borda internas do painelUse a panel's built-in border properties

Os controles Grid, StackPanel, RelativePanel e ContentPresenter têm propriedades de borda internas que permitem que você desenhe uma borda em torno deles sem acrescentar um elemento Border ao XAML.Grid, StackPanel, RelativePanel, and ContentPresenter controls have built-in border properties that let you draw a border around them without adding an additional Border element to your XAML. As novas propriedades que oferecem suporte à borda interna são: BorderBrush, BorderThickness, CornerRadius e preenchimento.The new properties that support the built-in border are: BorderBrush, BorderThickness, CornerRadius, and Padding. Cada um desses é um DependencyProperty, então você pode usá-los com ligações e animações.Each of these is a DependencyProperty, so you can use them with bindings and animations. Eles são feitos para serem uma substituição total para um elemento Border separado.They’re designed to be a full replacement for a separate Border element.

Se a sua interface do usuário tem elementos Border em torno desses painéis, use a borda interna ao invés, o que economiza um elemento extra na estrutura do layout de seu aplicativo.If your UI has Border elements around these panels, use the built-in border instead, which saves an extra element in the layout structure of your app. Como mencionado anteriormente, isso pode ser uma economia significativa, principalmente no caso de interface do usuário repetida.As mentioned previously, this can be a significant savings, especially in the case of repeated UI.

ExemplosExamples

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

Use eventos SizeChanged para responder a mudanças de layoutUse SizeChanged events to respond to layout changes

A classe FrameworkElement expõe dois eventos similares para responder a alterações de layout: LayoutUpdated e SizeChanged.The FrameworkElement class exposes two similar events for responding to layout changes: LayoutUpdated and SizeChanged. Você pode estar usando um desses eventos para receber notificações quando um elemento é redimensionado durante o layout.You might be using one of these events to receive notification when an element is resized during layout. A semântica dos dois eventos é diferente e existem considerações de desempenho importantes na escolha entre eles.The semantics of the two events are different, and there are important performance considerations in choosing between them.

Para um bom desempenho, SizeChanged é quase sempre a escolha certa.For good performance, SizeChanged is almost always the right choice. SizeChanged tem semântica intuitiva.SizeChanged has intuitive semantics. É gerado durante o layout quando o tamanho do FrameworkElement foi atualizado.It is raised during layout when the size of the FrameworkElement has been updated.

LayoutUpdated também é gerado durante o layout, mas tem uma semântica global: é gerado em cada elemento sempre que qualquer elemento for atualizado.LayoutUpdated is also raised during layout, but it has global semantics—it is raised on every element whenever any element is updated. É comum fazer apenas processamento local no manipulador de evento. Nesse caso, o código é executado com mais frequência que o necessário.It is typical to only do local processing in the event handler, in which case the code is run more often than needed. Use LayoutUpdated apenas se você precisar saber quando um elemento é reposicionado sem alteração de tamanho (o que é incomum).Use LayoutUpdated only if you need to know when an element is repositioned without changing size (which is uncommon).

Escolhendo painéisChoosing between panels

Desempenho não costuma ser uma consideração quando se escolhe entre painéis individuais.Performance is typically not a consideration when choosing between individual panels. Essa escolha costuma ser feita levando em consideração qual painel fornece o comportamento de layout mais próximo à interface do usuário que você está implementando.That choice is typically made by considering which panel provides the layout behavior that is closest to the UI you’re implementing. Por exemplo, se estiver escolhendo entre Grid, StackPanel e RelativePanel, você deve optar pelo painel que ofereça o mapeamento mais próximo de seu modelo mental da implementação.For example, if you’re choosing between Grid, StackPanel , and RelativePanel, you should choose the panel that provides the closest mapping to your mental model of the implementation.

Todo painel XAML é otimizado para obter bom desempenho, e todos os painéis oferecem um desempenho semelhante à interface do usuário semelhante.Every XAML panel is optimized for good performance, and all the panels provide similar performance for similar UI.