Auf Englisch lesen

Freigeben über


Layout

In diesem Thema wird das Layoutsystem von Windows Presentation Foundation (WPF) beschrieben. Das Verständnis, wie und wann Layoutberechnungen auftreten, ist für das Erstellen von Benutzeroberflächen in WPF unerlässlich.

Dieses Thema enthält die folgenden Abschnitte:

Umgebende Felder für Elemente

Wenn Sie an das Layout in WPF denken, ist es wichtig, die umgebenden Felder zu verstehen, die alle Elemente umschließen. Man kann sich jedes FrameworkElement, das vom Layoutsystem verwendet wird, als Rechteck vorstellen, das in das Layout eingepasst wird. Die LayoutInformation Klasse gibt die Begrenzungen der Layoutzuweisung oder des Steckplatzes eines Elements zurück. Die Größe des Rechtecks wird durch Berechnen des verfügbaren Bildschirmbereichs, der Größe aller Einschränkungen, layoutspezifischer Eigenschaften (z. B. Rand und Abstand) und dem individuellen Verhalten des übergeordneten Panel-Elements bestimmt. Durch Verarbeitung dieser Daten kann das Layoutsystem die Position aller untergeordneten Elemente eines bestimmten Panel berechnen. Es ist zu bedenken, dass die Größeneigenschaften für das übergeordnete Element definiert sind, z. B. eine Border-Klasse, die untergeordneten Elemente beeinflusst.

Die folgende Abbildung zeigt ein einfaches Layout.

Screenshot: Typisches Raster, ohne überlagerndes umgebendes Feld

Dieses Layout kann mithilfe des folgenden XAML-Codes erreicht werden.

XAML
<Grid Name="myGrid" Background="LightSteelBlue" Height="150">
  <Grid.ColumnDefinitions>
    <ColumnDefinition Width="250"/>
  </Grid.ColumnDefinitions>
  <Grid.RowDefinitions>
    <RowDefinition />
    <RowDefinition />
    <RowDefinition />
  </Grid.RowDefinitions>
  <TextBlock Name="txt1" Margin="5" FontSize="16" FontFamily="Verdana" Grid.Column="0" Grid.Row="0">Hello World!</TextBlock>
  <Button Click="getLayoutSlot1" Width="125" Height="25" Grid.Column="0" Grid.Row="1">Show Bounding Box</Button>
  <TextBlock Name="txt2" Grid.Column="1" Grid.Row="2"/>
</Grid>

Ein einzelnes TextBlock-Element wird in einem Grid gehostet. Während der Text nur die obere linke Ecke der ersten Spalte ausfüllt, ist der für die TextBlock zugewiesene Platz tatsächlich viel größer. Der Begrenzungsrahmen eines beliebigen FrameworkElement kann mit der GetLayoutSlot-Methode abgerufen werden. Die folgende Abbildung zeigt den Begrenzungsrahmen für das TextBlock-Element.

Screenshot: Das umgebende Feld für „TextBlock“ ist jetzt sichtbar.

Wie im gelben Rechteck gezeigt, ist der zugewiesene Platz für das TextBlock-Element tatsächlich viel größer als es angezeigt wird. Wenn dem Gridzusätzliche Elemente hinzugefügt werden, kann diese Zuordnung je nach Typ und Größe der hinzugefügten Elemente verkleinert oder erweitert werden.

Der Layout-Slot des TextBlock wird mit Hilfe der GetLayoutSlot-Methode in ein Path übersetzt. Diese Technik kann für das Anzeigen des Begrenzungsrahmens eines Elements nützlich sein.

C#
private void getLayoutSlot1(object sender, System.Windows.RoutedEventArgs e)
{
    RectangleGeometry myRectangleGeometry = new RectangleGeometry();
    myRectangleGeometry.Rect = LayoutInformation.GetLayoutSlot(txt1);
    Path myPath = new Path();
    myPath.Data = myRectangleGeometry;
    myPath.Stroke = Brushes.LightGoldenrodYellow;
    myPath.StrokeThickness = 5;
    Grid.SetColumn(myPath, 0);
    Grid.SetRow(myPath, 0);
    myGrid.Children.Add(myPath);
    txt2.Text = "LayoutSlot is equal to " + LayoutInformation.GetLayoutSlot(txt1).ToString();
}

Das Layoutsystem

In seiner einfachsten Form ist ein Layout ein rekursives System, das zur Größe, Positionierung und Darstellung eines Elements führt. Genauer gesagt, beschreibt das Layout den Prozess der Vermessung und Anordnung der Member einer Panel-Elementsammlung Children. Layout ist ein intensiver Prozess. Je größer die Children-Sammlung, desto höher die Anzahl von Berechnungen, die vorgenommen werden müssen. Komplexität kann auch basierend auf dem Layoutverhalten eingeführt werden, das im Panel-Element der Sammlung definiert ist. Eine relativ einfache Panel, wie z. B. Canvas, kann eine deutlich bessere Leistung als eine komplexere Panelaufweisen, z. B. Grid.

Immer wenn ein untergeordnetes UIElement-Element seine Position ändert, kann es einen neuen Durchlauf des Layoutsystems auslösen. Daher ist es wichtig, die Ereignisse zu verstehen, die das Layoutsystem aufrufen können, da unnötige Aufrufe zu einer schlechten Anwendungsleistung führen können. Im Folgenden wird der Prozess beschrieben, der auftritt, wenn das Layoutsystem aufgerufen wird.

  1. Der Layoutprozess eines untergeordneten UIElement-Elements beginnt mit der Messung von dessen Kerneigenschaften.

  2. Größenanpassungseigenschaften, die für FrameworkElement definiert sind, werden ausgewertet, z. B. Width, Height und Margin.

  3. Panel-spezifische Logik wird angewendet, z Dock . B. Richtung oder StapelungOrientation.

  4. Der Inhalt wird neu angeordnet, nachdem alle untergeordneten Elemente gemessen wurden.

  5. Die Children-Sammlung wird auf dem Bildschirm gezeichnet.

  6. Der Prozess wird erneut aufgerufen, wenn der Sammlung weitere Children hinzugefügt werden, LayoutTransform angewendet wird oder die UpdateLayout-Methode aufgerufen wird.

Dieser Prozess und dessen Aufruf werden in den folgenden Abschnitten ausführlicher definiert.

Messen und Anordnen von untergeordneten Elementen

Das Layoutsystem führt zwei Durchläufe für jeden Member in einer Children-Sammlung durch: einen Messdurchlauf und einen Anordnungsdurchlauf. Jedes untergeordnetes Panel bietet seine eigenen MeasureOverride- und ArrangeOverride-Methoden, um sein eigenes spezifisches Layout-Verhalten zu erreichen.

Während des Messdurchlaufs wird jedes Member der Children-Sammlung bewertet. Der Prozess beginnt mit einem Aufruf der Measure-Methode. Diese Methode wird in der Implementierung des übergeordneten Panel-Elements aufgerufen und muss nicht explizit aufgerufen werden, damit das Layout auftritt.

Zunächst werden die Eigenschaften der nativen Größe der UIElement bewertet, wie z. B. Clip und Visibility. Dadurch wird ein Wert namens constraintSize generiert, der an MeasureCoreübergeben wird.

Zweitens werden Rahmeneigenschaften, die für FrameworkElement definiert sind, verarbeitet, wodurch der Wert von constraintSizebeeinflusst wird. Diese Eigenschaften beschreiben in der Regel die Größeneigenschaften der zugrunde liegenden UIElement, z. B. deren Height, Width, Marginund Style. Jede dieser Eigenschaften kann den Platz ändern, der zum Anzeigen des Elements erforderlich ist. MeasureOverride wird dann mit constraintSize als Parameter aufgerufen.

Hinweis

Es gibt einen Unterschied zwischen den Eigenschaften von Height und Width und ActualHeight und ActualWidth. Die ActualHeight-Eigenschaft ist beispielsweise ein berechneter Wert, der auf anderen Höheneingaben und dem Layoutsystem basiert. Der Wert wird vom Layoutsystem selbst festgelegt, basierend auf einem tatsächlichen Renderingdurchlauf, und kann daher etwas hinter den festgelegten Wert von Eigenschaften zurückfallen, die die Grundlagen der Eingabeänderung sind, z. B. Height.

Da ActualHeight ein berechneter Wert ist, sollten Sie beachten, dass es mehrere oder inkrementelle gemeldete Änderungen daran als Ergebnis verschiedener Vorgänge des Layoutsystems geben könnte. Das Layoutsystem berechnet möglicherweise den Bereich für untergeordnete Elemente, Einschränkungen durch übergeordnete Elemente usw.

Das ultimative Ziel des Maßnahmendurchlaufs ist, dass das Untergeordnete seine DesiredSize bestimmt, das während des MeasureCore-Aufrufs auftritt. Der DesiredSize-Wert wird zur Verwendung während des Durchlaufs der Inhaltsvermittlung von Measure gespeichert.

Der Arrangier-Prozess beginnt mit einem Aufruf der Arrange-Methode. Während des Anordnungsdurchgangs generiert das übergeordnete Panel-Element ein Rechteck, das die Begrenzungen des untergeordneten Elements darstellt. Dieser Wert wird zur Verarbeitung an die ArrangeCore-Methode übergeben.

Die ArrangeCore-Methode wertet die DesiredSize des untergeordneten Elements aus und bewertet alle zusätzlichen Ränder, die sich auf die gerenderte Größe des Elements auswirken können. ArrangeCore generiert einen arrangeSize, der an die ArrangeOverride-Methode des Panel als Parameter übergeben wird. ArrangeOverride generiert finalSize des untergeordneten Elements. Abschließend führt die ArrangeCore-Methode eine letzte Auswertung von Offset-Eigenschaften durch, z. B. Rand und Anordnung, und fügt das untergeordnete Element in den Layoutslot ein. Das Kind muss den gesamten zugewiesenen Platz nicht ausfüllen und tut dies häufig auch nicht. Das Steuerelement wird daraufhin an das übergeordnete Panel-Element zurückgegeben, und der Layoutvorgang wird abgeschlossen.

Panel-Elemente und benutzerdefiniertes Layoutverhalten

WPF enthält eine Gruppe von Elementen, die von Panelabgeleitet werden. Diese Panel Elemente ermöglichen viele komplexe Layouts. Beispielsweise kann das Stapeln von Elementen mithilfe des StackPanel-Elements einfach erreicht werden, während komplexere und frei fließende Layouts mit einem Canvasmöglich sind.

In der folgenden Tabelle sind die verfügbaren Layoutelemente Panel zusammengefasst.

Panelname Beschreibung
Canvas Definiert einen Bereich, in dem Sie mithilfe von Koordinaten, die relativ zum Canvas-Bereich sind, explizit untergeordnete Elemente positionieren können.
DockPanel Definiert einen Bereich, in dem Sie untergeordnete Elemente entweder horizontal oder vertikal relativ zueinander anordnen können.
Grid Definiert einen flexiblen Rasterbereich, der aus Spalten und Zeilen besteht.
StackPanel Ordnet untergeordnete Elemente in einer einzelnen Zeile an, die horizontal oder vertikal ausgerichtet werden kann.
VirtualizingPanel Stellt ein Framework für Panel-Elemente bereit, die ihre untergeordnete Datensammlung virtualisieren. Dies ist eine abstrakte Klasse.
WrapPanel Ordnet untergeordnete Elemente nacheinander von links nach rechts und bricht den Inhalt in die nächste Zeile am Rand des enthaltenden Felds um. Nachfolgende Sortierung erfolgt sequenziell von oben nach unten oder von rechts nach links, je nach Wert der Orientation-Eigenschaft.

Für Anwendungen, die ein Layout benötigen, das mit den vordefinierten Panel-Elementen nicht möglich ist, können Sie benutzerdefinierte Layout-Verhaltensweisen erreichen, indem Sie von den Panel erben und die MeasureOverride- und ArrangeOverride-Methoden überschreiben.

Überlegungen zur Leistungsfähigkeit des Layouts

Layout ist ein rekursiver Prozess. Jedes untergeordnete Element in einer Children-Sammlung wird bei jedem Aufruf des Layoutsystems verarbeitet. Daher sollte das Auslösen des Layoutsystems vermieden werden, wenn es nicht erforderlich ist. Die folgenden Überlegungen können Ihnen helfen, eine bessere Leistung zu erzielen.

  • Beachten Sie, welche Eigenschaftswertänderungen eine rekursive Aktualisierung durch das Layoutsystem erzwingen.

    Abhängigkeitseigenschaften, deren Werte bewirken, dass das Layoutsystem initialisiert werden kann, werden mit öffentlichen Flags gekennzeichnet. AffectsMeasure und AffectsArrange liefern nützliche Hinweise dazu, welche Eigenschaftswertänderungen eine rekursive Aktualisierung durch das Layoutsystem erzwingen. Im Allgemeinen muss jede Eigenschaft, die die Größe des umgebenden Felds eines Elements beeinflussen kann, über ein AffectsMeasure-Flag verfügen, das auf TRUE festgelegt ist. Weitere Informationen finden Sie unter Übersicht über Abhängigkeitseigenschaften.

  • Wenn möglich, verwenden Sie anstelle RenderTransform einer LayoutTransform.

    LayoutTransform kann eine sehr nützliche Methode sein, um den Inhalt einer Benutzeroberfläche (UI) zu beeinflussen. Wenn sich die Auswirkung der Transformation jedoch nicht auf die Position anderer Elemente auswirken muss, empfiehlt es sich stattdessen, eine RenderTransform zu verwenden, da RenderTransform das Layoutsystem nicht aufruft. LayoutTransform wendet seine Transformation an und erzwingt eine rekursive Layoutaktualisierung, um die neue Position des betroffenen Elements zu berücksichtigen.

  • Vermeiden Sie unnötige Aufrufe an UpdateLayout.

    Die UpdateLayout Methode erzwingt eine rekursive Layoutaktualisierung und ist häufig nicht erforderlich. Wenn Sie nicht sicher sind, dass ein vollständiges Update erforderlich ist, verlassen Sie sich auf das Layoutsystem, um diese Methode für Sie aufzurufen.

  • Wenn Sie mit einer großen Children-Sammlung arbeiten, sollten Sie einVirtualizingStackPanel anstelle eines normalen StackPanel verwenden.

    Durch das Virtualisieren der untergeordneten Sammlung behält VirtualizingStackPanel nur Objekte im Speicher, die sich derzeit innerhalb des ViewPort der übergeordneten Sammlung befindet. Daher wird die Leistung in den meisten Szenarien erheblich verbessert.

Subpixel-Rendering und Layoutglättung

Das WPF-Grafiksystem verwendet geräteunabhängige Einheiten, um Auflösung und Geräteunabhängigkeit zu ermöglichen. Jedes geräteunabhängige Pixel wird automatisch skaliert, um mit der DPI-Einstellung (Dots Per Inch) des Systems übereinzustimmen, auf dem das Pixel gerendert wird. Dadurch wird die ordnungsgemäße Skalierung von WPF-Anwendungen für unterschiedliche dpi-Einstellungen bereitgestellt, und die Anwendung ist automatisch bereit für dpi.

Jedoch kann diese DPI-Unabhängigkeit unregelmäßiges Edge-Rendering aufgrund von Antialiasing hervorrufen. Diese Artefakte, die in der Regel als verschwommene oder halbtransparente Kanten angesehen werden, können auftreten, wenn die Position eines Rands in der Mitte eines Gerätepixels anstatt zwischen Gerätepixeln fällt. Das Layoutsystem bietet eine Möglichkeit, dafür eine Anpassung durch Layoutglättung vorzunehmen. Die Layoutglättung wird verwendet, wo Layoutsysteme nicht-integrale Pixelwerte während des Layoutdurchlaufs glättet.

Die Layoutglättung ist standardmäßig deaktiviert. Um die Layout-Rundung zu aktivieren, setzen Sie die UseLayoutRounding-Eigenschaft auf true auf beliebige FrameworkElement. Da es sich um eine Abhängigkeitseigenschaft handelt, wird der Wert an alle untergeordneten Elemente in der visuellen Struktur weitergegeben. Um die Layout-Rundung für die gesamte Benutzeroberfläche zu aktivieren, setzen Sie UseLayoutRounding auf true auf den Stammcontainer. Ein Beispiel finden Sie unter UseLayoutRounding.

Was kommt als nächstes

Das Verständnis, wie Elemente gemessen und angeordnet werden, ist der erste Schritt beim Verständnis des Layouts. Weitere Informationen über verfügbare Panel-Elemente finden Sie unter Übersicht über Bereiche. Weitere Informationen über die verschiedenen Positionierungseigenschaften, die das Layout beeinflussen können, finden Sie unter Übersicht über Alignment, Margin und Padding. Wenn Sie bereit sind, alles in einer einfachen Anwendung zusammenzustellen, lesen Sie Walkthrough: Meine erste WPF-Desktopanwendung.

Siehe auch