Anordnen von Ansichten mit Grid

Abgeschlossen

Angenommen, Sie erstellen eine Seite, die Bilder in einem 7×5-Raster anzeigt. Es wäre möglich, hierfür mehrere horizontale und vertikale StackLayout-Container zu verwenden. Die Programmierung wäre aber ausgesprochen mühsam, und es könnte aufgrund der Arbeitsspeicher- und Verarbeitungsanforderungen mehrerer Layoutpanels zu Leistungsproblemen kommen. Das Layoutpanel Grid ist die bessere Wahl für Benutzeroberflächen, auf denen sowohl Zeilen als auch Spalten benötigt werden. In dieser Einheit erfahren Sie, wie Sie ein Raster (Grid) definieren und Ansichten in den Zellen positionieren.

Was ist ein Grid-Layout?

Ein Raster (Grid) ist ein Layoutpanel, das aus Zeilen und Spalten besteht. Die folgende Abbildung zeigt eine konzeptionelle Ansicht eines solchen Rasters.

Abbildung: Beispielraster mit Zeilen und Spalten von Feldern, dabei streckt sich ein Feld über mehrere Zeilen und Spalten

Sie platzieren View-Elemente in den Zellen, die durch die Überschneidung der Zeilen und Spalten entstehen. Wenn Sie beispielsweise ein Raster (Grid) mit drei Spalten und zwei Zeilen erstellen, stehen sechs Zellen für Ansichten zur Verfügung. Die Zeilen und Spalten können unterschiedliche Größen aufweisen oder so eingerichtet werden, dass sie sich automatisch an die untergeordneten Elemente anpassen, die in den Zellen platziert werden. Untergeordnete Ansichten können eine Zelle belegen oder sich über mehrere Zellen erstrecken. Aufgrund dieser Flexibilität ist Grid eine gute Wahl für das Stammlayoutpanel vieler Apps.

Angeben der Zeilen und Spalte eines Grid-Layouts

Wenn Sie ein Griderstellen, können Sie jede Zeile und Spalte einzeln definieren. Dieses System bietet Ihnen vollständige Kontrolle über die Höhe jeder Zeile und die Breite jeder Spalte. Jedes Grid verfügt über eine Sammlung aus RowDefinition- und ColumnDefinition-Objekten, die die Form des Rasters definieren. Sie füllen diese Sammlungen mit Instanzen von RowDefinition und ColumnDefinition auf, die jeweils eine Zeile bzw. eine Spalte Ihrer Benutzeroberfläche darstellen.

Die folgenden beiden Codeausschnitte zeigen die Klassendefinitionen für RowDefinition und ColumnDefinition:

public sealed class RowDefinition : ...
{
    ...
    public GridLength Height { get; set; }
}
public sealed class ColumnDefinition : ...
{
    ...
    public GridLength Width { get; set; }
}

Beachten Sie, dass RowDefinition eine Eigenschaft namens Height und ColumnDefinition eine Eigenschaft namens Width besitzt. Sie verwenden diese Eigenschaften, um die Höhe einer Zeile und die Breite einer Spalte festzulegen, wie in den folgenden Abschnitten beschrieben.

Was ist GridLength?

Der Datentyp für die Eigenschaften Width und Height ist GridLength. Dieser Typ enthält zwei Eigenschaften: GridUnitType und Value. Der folgende Codeausschnitt zeigt einen Teil der Typdefinition.

public struct GridLength
{
    ...
    public GridUnitType GridUnitType { get; }
    public double Value { get; }
}

Sie können die Eigenschaft GridUnitType auf einen der folgenden Werte festlegen:

  • Absolute
  • Auto
  • Star

Sehen wir uns die einzelnen Werte einmal näher an.

GridUnitType: Absolute

Absolute gibt an, dass die Zeile oder Spalte eine feste Größe haben soll. Die Eigenschaft Value dient zum Angeben der Größe. Das folgende Beispiel zeigt, wie Sie in C# die Höhe einer Zeile auf die feste Größe von 100 Geräteeinheiten festlegen. Beachten Sie, wie Sie den GridLength-Konstruktor verwenden, der einen numerischen Wert akzeptiert. Der Konstruktor legt GridUnitType automatisch auf Absolute fest.

var row = new RowDefinition() { Height = new GridLength(100) };

In Extensible Application Markup Language (XAML) geben Sie einfach einen numerischen Wert an. Der XAML-Parser ruft einen Typkonverter auf, um die GridLength-Instanz zu erstellen. Das folgende Beispiel zeigt das Gleiche in XAML:

<RowDefinition Height="100" />

GridUnitType: Auto

Auto passt die Größe der Zeilen oder Spalten automatisch an die untergeordneten Ansichten an. Das Raster (Grid) überprüft alle untergeordneten Ansichten in der entsprechenden Zeile oder Spalte, wählt die größte Ansicht aus und macht die Zeile oder Spalte so groß, dass diese untergeordnete Ansicht hineinpasst. Wenn Sie eine Zeilendefinition per Code erstellen, wird der numerische Wert ignoriert. Sie können einen beliebigen Wert verwenden. Das folgende Beispiel zeigt, wie Sie in C# die Höhe einer Zeile so festlegen, dass die Größe automatisch angepasst wird. Beachten Sie, dass wir hier willkürlich 1 als Wert ausgewählt haben.

var row = new RowDefinition() { Height = new GridLength(1, GridUnitType.Auto) };

In XAML verwenden Sie den Wert Auto. Das folgende Beispiel zeigt das Gleiche in XAML:

<RowDefinition Height="Auto" />

GridUnitType: Star

Star ermöglicht eine proportionale Größenanpassung. Bei der proportionalen Größenanpassung wird die Größe durch den insgesamt verfügbaren Platz und das Verhältnis bestimmt, das für die einzelnen Zeilen oder Spalten erforderlich ist. Dies wird häufig auch als Größenanpassung mit Sternvariabler anstatt als proportionale Größenanpassung bezeichnet.

Sehen wir uns den Prozess der proportionalen Größenanpassung für die Zeilen in einem Raster einmal an.

  1. Bestimmen Sie den verfügbaren Platz: Das Grid überprüft alle Zeilen, die Grid die Größenanpassung mit Sternvariable verwenden. Die Höhen all dieser Zeilen werden addiert, und diese Gesamtsumme wird von der Höhe des Grid-Elements selbst subtrahiert. Diese Berechnung gibt den Platz an, der für alle Zeilen mit Sternvariabler insgesamt verfügbar ist.

  2. Teilen Sie den verfügbaren Platz auf: Das Grid teilt den verfügbaren Platz auf alle Zeilen mit Sternvariabler auf, basierend auf der Value-Einstellung für jede Zeile. Stellen Sie sich die Value-Eigenschaft als Multiplikator vor, der das Verhältnis zwischen allen Zeilen bestimmt, die als „mit Sternvariabler“ definiert sind. Ein Beispiel: Sie haben zwei Zeilen mit Sternvariabler, die beide 1 als Multiplikator aufweisen. Dann wird der verfügbare Platz gleichmäßig auf beide Zeilen aufgeteilt. Wenn jedoch eine der beiden Zeilen 2 als Wert aufwiese, würde sie doppelt so viel Platz erhalten wie die andere.

Das folgende Beispiel zeigt, wie Sie in C# die Höhe einer Zeile als 2 Star festlegen:

var row = new RowDefinition() { Height = new GridLength(2, GridUnitType.Star) };

In XAML verwenden Sie das Symbol *, um die Größenanpassung mit Sternvariabler darzustellen. Sie kombinieren den Wert und das *-Symbol in einer einzigen Zeichenfolge, und ein Typkonverter erstellt die GridLength für Sie. Hier sehen Sie das Beispiel in XAML.

<RowDefinition Height="2*" />

Grid-Sammlungen

Nachdem Sie Zeilen und Spalten mithilfe von RowDefinition und ColumnDefinition definiert haben, können Sie sie einem Raster (Grid) hinzufügen. Sie verwenden die Sammlungseigenschaften RowDefinitions und ColumnDefinitions des Grid. Das Auffüllen dieser Sammlungen erfolgt meistens in XAML.

Dieses Beispiel zeigt, wie Sie vier Zeilen definieren und mithilfe der RowDefinitions-Eigenschaft zu einem Grid hinzufügen:

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="100" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="1*" />
        <RowDefinition Height="2*" />
    </Grid.RowDefinitions>
    ...
</Grid>

Diese Definition kann wie folgt gekürzt werden:

<Grid RowDefinitions="100, Auto, 1*, 2*">
    ...
</Grid>

Der XAML-Code zum Definieren von Spalten entspricht dem vorherigen XAML. Abgesehen davon, dass Sie ColumnDefinitions verwenden und den Wert für Width angeben würden.

Zur Laufzeit erzeugt dieser XAML-Code ein Raster (Grid) mit vier Zeilen. Die erste Zeile hat eine feste Höhe von 100 Geräteeinheiten. Die zweite Zeile hat die Höhe der höchsten Ansicht in der Zeile. Die dritte und vierte Zeile verwenden die Größenanpassung mit Sternvariabler. Das bedeutet, dass der verbleibende verfügbare Platz basierend auf dem Value-Multiplikator proportional aufgeteilt wird. Da der Multiplikator für die dritte Zeile 1* und für die vierte Zeile 2* lautet, ist die vierte Zeile doppelt so hoch wie die dritte.

Standardgröße für Zeilen und Spalten

Der Standardwert für Zeilen und Spalten ist die Größe 1*. Sehen Sie sich beispielsweise folgende XAML an:

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition />
        <RowDefinition />
        <RowDefinition />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition />
        <ColumnDefinition />
    </Grid.ColumnDefinitions>
    ...
</Grid>

Diese Definition kann wie folgt gekürzt werden:

<Grid RowDefinitions="*, *, *" ColumnDefinitions="*, *">
    ...
</Grid>

Da für keine der Zeilen oder Spalten eine Größe angegeben ist, wird 1* auf alle angewendet. Zur Laufzeit erstellt diese Konfiguration ein gleichförmiges Raster (Grid), was bedeutet, dass alle Zeilen die gleiche Höhe und alle Spalten die gleiche Breite aufweisen.

Hinzufügen von Ansichten zu einem Grid

Wenn Sie einem Grid eine Ansicht hinzufügen, fügen Sie sie einer bestimmten Zelle hinzu. Zellen werden an Positionen erstellt, an denen Zeilen und Spalten sich überschneiden. Um eine Ansicht in einer Zelle zu platzieren, müssen Sie die Position der Zelle kennen. Sie verwenden eine Kombination aus einer Zeilennummer und einer Spaltennummer, um eine Zelle zu identifizieren.

Nummerierung von Zeilen und Spalten

Die Nummerierung von Zeilen und Spalten beginnt bei Null. Der Ursprung ist die linke obere Ecke. Die folgende Abbildung zeigt die Nummerierung für ein Grid-Element mit vier Zeilen und zwei Spalten.

Abbildung: Grid-Layout mit vier Zeilen und zwei Spalten. Die Nummerierung wird für jede Zeile und Spalte angezeigt. Beginnend mit dem oberen linken Feld bei Spalte 0 und Zeile 0 bis zum unteren rechten Feld bei Spalte 1 und Zeile 3.

Wenn Sie beispielsweise der rechten unteren Zelle eine Ansicht hinzufügen möchten, wird die Position der Ansicht folgendermaßen angegeben: row 3 column 1.

Hinzufügen einer Ansicht zu einem Grid mithilfe von angefügten Eigenschaften

Sie benötigen eine Möglichkeit, die Zeilen- und Spaltennummer einer Ansicht anzugeben, wenn Sie diese einem Grid hinzufügen. Eine Lösung wäre, Row- und Column-Eigenschaften in der View-Basisklasse zu definieren, sodass Sie die Position der Ansicht direkt angeben können. Dieses Verfahren würde funktionieren, ist aber nicht der effizienteste Ansatz. Ansichten befinden sich nicht immer in einem Grid, daher werden diese Eigenschaften möglicherweise nicht benötigt. Eine bessere Vorgehensweise ist die Verwendung von angefügten Eigenschaften.

Eine angefügte Eigenschaft ist eine Eigenschaft, die in einer einzelnen Klasse definiert, aber für Objekte anderer Typ festgelegt wird.

Sie können sich angefügte Eigenschaften als Sammlung aus Schlüssel-Wert-Paaren vorstellen, die Teil einer Ansicht ist. Wenn Sie einem Grid eine Ansicht hinzufügen, geben Sie die Zeile und Spalte an. Durch Verwendung von angefügten Eigenschaften können Sie ein Schlüssel-Wert-Paar mit dem Schlüssel Grid.Row und einem Wert, der die Zeilennummer angibt, hinzufügen. Wenn das Raster (Grid) bereit ist, die Ansicht zu positionieren, überprüft es die Sammlung, um zu ermitteln, ob ein Schlüssel namens Grid.Row vorhanden ist. Falls ja, verwendet das Raster (Grid) diesen Wert, um die Ansicht zu positionieren.

Dieses Beispiel zeigt, wie Sie ein Grid erstellen und mithilfe von angefügten Eigenschaften eine Ansicht hinzufügen:

<Grid RowDefinitions="*, *, *" ColumnDefinitions="*, *">

    <BoxView Grid.Row="1" Grid.Column="0" Color="Navy" />
    
</Grid>

In diesem Beispiel sind Grid.Row=1 und Grid.Column=0 Schlüssel-Wert-Paare, die einer internen Sammlung der BoxView hinzugefügt werden. Das Raster (Grid) verwendet diese Werte, um zu ermitteln, wo die Ansicht positioniert werden soll. So sieht das Grid-Element aus, wenn Sie die Anwendung auf einem Gerät ausführen:

Abbildung eines Rasters mit drei Zeilen und zwei Spalten. In der zweiten Zeile der ersten Spalte wird ein BoxView-Element angezeigt.

Festlegen einer Ansicht über mehrere Zeilen oder Spalten

Es gibt zwei weitere angefügte Eigenschaften, die Sie kennen sollten: Grid.RowSpan und Grid.ColumnSpan. Diese Eigenschaften geben an, wie viele Zeilen oder Spalten die Ansicht einnehmen soll. Sehen Sie sich beispielsweise folgende XAML an:

<Grid RowDefinitions="*, *, *" ColumnDefinitions="*, *">

    <BoxView Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" Color="Navy" />
    
</Grid>

Beachten Sie, dass in diesem Beispiel ColumnSpan auf 2 festgelegt wird. Diese Ansicht belegt zwei Spalten ab Column 0. So sieht das Grid-Element aus, wenn Sie die Anwendung auf einem Gerät ausführen:

Darstellung eines Rasters mit drei Zeilen und zwei Spalten. Die zweite Zeile der ersten Spalte enthält ein BoxView-Element, das sich über beide Spalten erstreckt.

Wissensbeurteilung

1.

Welchen Zweck hat Star GridUnitType?