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 Grid definieren und Ansichten in den Zellen positionieren.

Was ist ein Grid-Layout?

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

Illustration showing an example grid with rows and columns of boxes, with one box spanning multiple rows and columns.

Sie platzieren View-Elemente in den Zellen, die durch die Überschneidung der Zeilen und Spalten entstehen. Wenn Sie beispielsweise ein Grid erstellen, das aus drei Spalten und zwei Zeilen besteht, 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 Grid erstellen, müssen Sie jede Zeile und jede 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. Ihre Aufgabe ist es, diese Sammlungen mit Instanz von RowDefinition und ColumnDefinition aufzufüllen, die jeweils eine Zeile bzw. Spalte der Benutzeroberfläche repräsentieren.

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.

Was ist GridLength?

Der Datentyp für Width und Height lautet 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 aufweist. Mit der Eigenschaft Value geben Sie die Größe an. 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, dass 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 XAML verwenden wir einfach einen numerischen Wert. 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 Grid überprüft alle untergeordneten Ansichten in der entsprechenden Zeile oder Spalte, wählt die größte Ansicht aus und richtet die Zeile oder Spalte so groß ein, 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. Die Größe wird durch den insgesamt verfügbaren Platz und das Verhältnis bestimmt, der bzw. das von den einzelnen Zeilen oder Spalten angefordert wird. 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 aber eine der beiden Zeilen einen Value von 2 hätte, 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

Sie wissen jetzt, wie Sie mithilfe vonRowDefinition und ColumnDefinition Zeilen und Spalten definieren. Als Nächstes müssen Sie diese zu einem Grid hinzufügen. Dazu verwenden Sie Sammlungseigenschaften RowDefinitions und ColumnDefinitions von Grid. Das Auffüllen dieser Sammlungen erfolgt im häufigsten in XAML, daher verwenden wir diese Sprache in unseren Beispielen.

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>

Die XAML zum Definieren von Spalten entspricht dieser XAML, mit der Ausnahme, dass Sie ColumnDefinitions verwenden und die Breite festlegen.

Zur Laufzeit erzeugt diese XAML ein Grid mit vier Zeilen. Die erste Zeile weist eine feste Höhe von 100 Geräteeinheiten auf. Die zweite Zeile weist die Höhe der höchsten Ansicht in der Zeile auf. Die dritte und vierte Zeile verwenden die Größenanpassung mit Sternvariabler. Das bedeutet, dass sie den verbleibenden verfügbaren Platz basierend auf dem Value-Multiplikator proportional aufteilen. 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>

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 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 eine Ansicht zu einem Grid hinzufügen, fügen Sie sie zu einer bestimmten Zelle hinzu. Zellen werden an Positionen erstellt, an denen Zeilen und Spalten sich überschneiden. Um eine Ansicht in einer Zelle platzieren, müssen wir 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.

Illustration showing a grid with four rows and two columns and the numbering for each, from the top left box at column zero and row zero to the bottom right box at column one and row 3.

Wenn Sie beispielsweise eine Ansicht zur rechten unteren Zelle 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

Wir benötigen eine Möglichkeit, die Zeilen- und Spaltennummer einer Ansicht anzugeben, wenn diese zu einem Grid hinzugefügt wird. Eine Lösung wäre, Row- und Column-Eigenschaften in der View-Basisklasse zu definieren, sodass wir 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 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. Wir verwenden Grid als Beispiel. Wenn Sie eine Ansicht zu einem Grid hinzufügen, müssen Sie die Zeile und die Spalte angeben. Durch Verwendung von angefügten Eigenschaften können Sie ein Schlüssel-Wert-Paar mit dem Schlüssel Grid.Row und einem Wert hinzufügen, bei dem es sich um die Position der Zeile handelt. Wenn das Grid bereit ist, die Ansicht zu positionieren, überprüft es die Sammlung, um zu ermitteln, ob ein Schlüssel namens Grid.Row vorhanden ist. Wenn dies der Fall ist, verwendet das Grid diesen Wert zum Positionieren der Ansicht.

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

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

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

Wie Sie sehen, sind Grid.Row=1 und Grid.Column=0 Schlüssel-Wert-Paare, die einer internen Sammlung der BoxView hinzugefügt werden. Das 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:

Illustration showing a Grid with three rows and two columns. A BoxView is displayed in the second row of the first column.

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>
    <Grid.RowDefinitions>
        <RowDefinition />
        <RowDefinition />
        <RowDefinition />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition />
        <ColumnDefinition />
    </Grid.ColumnDefinitions>

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

In diesem Beispiel legen wir den Wert für ColumnSpan auf 2 fest. Diese Ansicht belegt zwei Spalten ab dem Column-Element mit dem Wert 0. So sieht das Grid-Element aus, wenn Sie die Anwendung auf einem Gerät ausführen:

Illustration showing a Grid with three rows and two columns. A BoxView is positioned in the second row of the first column and spans both columns.