Freigeben über


Optimieren Sie Ihr XAML-Layout

Wichtige APIs

Layout ist der Prozess der Definition der visuellen Struktur für Die Benutzeroberfläche. Der primäre Mechanismus zum Beschreiben des Layouts in XAML besteht aus Bereichen, bei denen es sich um Containerobjekte handelt, mit denen Sie die UI-Elemente darin positionieren und anordnen können. Das Layout kann ein teurer Teil einer XAML-App sein – sowohl bei der CPU-Auslastung als auch beim Arbeitsspeicheraufwand. Hier sind einige einfache Schritte, die Sie ausführen können, um die Layoutleistung Ihrer XAML-App zu verbessern.

Layoutstruktur reduzieren

Der größte Gewinn bei der Layoutleistung wird durch die Vereinfachung der hierarchischen Struktur des Baums der UI-Elemente erzielt. Panels sind in der visuellen Struktur vorhanden, aber sie sind strukturelle Elemente, nicht Pixel produzierende Elemente wie eine Button oder ein Rectangle. Das Vereinfachen der Baumstruktur durch Verringern der Anzahl der Elemente, die keine Pixel erzeugen, bietet in der Regel eine erhebliche Leistungssteigerung.

Viele Benutzeroberflächen werden durch verschachtelte Panels implementiert, was zu tiefen, komplexen Strukturen von Panels und Elementen führt. Es ist praktisch, Panels zu verschachteln, aber in vielen Fällen kann dieselbe Benutzeroberfläche mit einem komplexeren einzelnen Panel erreicht werden. Die Verwendung eines einzelnen Panels bietet eine bessere Leistung.

Wann die Layoutstruktur reduziert werden sollte

Das Layout auf einfache Weise zu reduzieren – z. B. ein geschachteltes Panel von Ihrer Top-Level-Seite zu entfernen – hat keinen spürbaren Effekt.

Die größten Leistungsgewinne erzielen Sie durch die Reduzierung der Layoutstruktur, die auf der Benutzeroberfläche wiederholt wird, zum Beispiel in einer ListView- oder einer GridView-. Diese ItemsControl Elemente verwenden eine DataTemplate, die eine Unterstruktur von UI-Elementen definiert, die mehrmals instanziiert werden. Wenn dieselbe Unterstruktur in Ihrer App mehrmals dupliziert wird, hat jede Verbesserung der Leistung dieser Unterstruktur einen multiplizierten Effekt auf die Gesamtleistung Ihrer App.

Beispiele

Betrachten Sie die folgende Benutzeroberfläche.

Formular-Layoutbeispiel

In diesen Beispielen werden drei Methoden zum Implementieren derselben Benutzeroberfläche gezeigt. Jede Implementierungsauswahl führt zu nahezu identischen Pixeln auf dem Bildschirm, unterscheidet sich jedoch erheblich in den Implementierungsdetails.

Option1: Verschachtelte StackPanel--Elemente

Obwohl dies das einfachste Modell ist, verwendet es 5 Panelelemente und führt zu erheblichem Mehraufwand.

  <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>

Option 2: Ein einzelnes Gitter

Das Grid- fügt etwas Komplexität hinzu, verwendet jedoch nur ein einzelnes 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>

Option 3: Ein einzelner RelativePanel:

Dieses einzelne Panel ist auch etwas komplexer als die Verwendung geschachtelter Panels, kann jedoch einfacher zu verstehen und zu verwalten sein als ein 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>

Wie in diesen Beispielen gezeigt, gibt es viele Möglichkeiten, die gleiche Benutzeroberfläche zu erreichen. Sie sollten wählen, indem Sie alle Kompromisse sorgfältig prüfen, einschließlich Leistung, Lesbarkeit und Wartbarkeit.

Verwenden Sie Einzellenraster für die überlappende UI

Eine allgemeine UI-Anforderung besteht darin, ein Layout zu haben, in dem sich Elemente überlappen. In der Regel werden Abstand, Ränder, Ausrichtungen und Transformationen verwendet, um die Elemente auf diese Weise zu positionieren. Das XAML-Grid-Steuerelement ist optimiert, um die Layoutleistung für Elemente zu verbessern, die sich überlappen.

Wichtig Um die Verbesserung zu sehen, verwenden Sie ein einzelnes Zellen-Raster-. Definieren Sie in RowDefinitions oder in ColumnDefinitions nicht.

Beispiele

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

Text überlagert auf einem Kreis

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

Zwei Textblöcke in einem Raster

Verwenden der integrierten Rahmeneigenschaften eines Panels

Grid, StackPanel, RelativePanelund ContentPresenter -Steuerelemente verfügen über integrierte Rahmeneigenschaften, mit denen Sie einen Rahmen um sie zeichnen können, ohne dem XAML-Code ein zusätzliches Border-Element hinzuzufügen. Die neuen Eigenschaften, die den integrierten Rahmen unterstützen, sind: BorderBrush, BorderThickness, CornerRadiusund Padding. Jede dieser Elemente ist ein DependencyProperty-, sodass Sie sie mit Bindungen und Animationen verwenden können. Sie sind als vollständiger Ersatz für ein separates Border-Element konzipiert.

Wenn Ihre Benutzeroberfläche über Border-Elemente um diese Panels verfügt, verwenden Sie stattdessen den integrierten Rahmen, wodurch ein zusätzliches Element in der Layoutstruktur Ihrer App eingespart wird. Wie bereits erwähnt, kann dies zu erheblichen Einsparungen führen, insbesondere bei wiederholten Benutzeroberflächen.

Beispiele

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

Verwenden Sie SizeChanged- Ereignisse, um auf Layoutänderungen zu reagieren.

Die FrameworkElement Klasse macht zwei ähnliche Ereignisse zur Reaktion auf Layoutänderungen verfügbar: LayoutUpdated und SizeChanged. Möglicherweise verwenden Sie eines dieser Ereignisse, um Benachrichtigungen zu erhalten, wenn die Größe eines Elements während des Layouts geändert wird. Die Semantik der beiden Ereignisse ist unterschiedlich, und es gibt wichtige Leistungsaspekte bei der Auswahl.

Für eine gute Leistung ist SizeChanged fast immer die richtige Wahl. SizeChanged- hat intuitive Semantik. Das Ereignis wird während der Layout-Phase ausgelöst, wenn die Größe des FrameworkElements,, aktualisiert wurde.

LayoutUpdated- wird auch während des Layouts ausgelöst, verfügt jedoch über globale Semantik– es wird bei jedem Element ausgelöst, wenn ein Element aktualisiert wird. Es ist typisch, nur die lokale Verarbeitung im Ereignishandler durchzuführen, in diesem Fall wird der Code häufiger als erforderlich ausgeführt. Verwenden Sie LayoutUpdated nur, wenn Sie wissen müssen, wann ein Element neu positioniert wird, ohne die Größe zu ändern (was ungewöhnlich ist).

Auswählen zwischen Paneelen

Die Leistung wird typischerweise nicht bei der Entscheidung zwischen einzelnen Paneelen berücksichtigt. Diese Wahl wird in der Regel getroffen, indem berücksichtigt wird, welches Panel das Layoutverhalten bereitstellt, das der von Ihnen implementierten Benutzeroberfläche am nächsten kommt. Wenn Sie z. B. zwischen Grid, StackPanel- und RelativePanel-wählen, sollten Sie das Panel auswählen, das die nächstgelegene Zuordnung zu Ihrem mentalen Modell der Implementierung bereitstellt.

Jedes XAML-Panel ist für eine gute Leistung optimiert, und alle Panels bieten eine ähnliche Leistung für ähnliche UI.