20.7 Grid
Der flexibelste Container ist das Grid. Es hat viel mehr Eigenschaften als das UniformGrid und erlaubt damit eine deutlich feinere Kontrolle über das Layout. Zum Beispiel kann sich eine Komponente in einem Grid über mehrere Zellen erstrecken.
Die höhere Flexibilität wird durch eine etwas komplexere Syntax erkauft. Allein die Zeilen- und Spaltenzahl reicht nicht mehr, sondern jede Zeile und jede Spalte wird getrennt spezifiziert. Durch die separaten Angaben kann jede Zeile und jede Spalte bei Bedarf individuell gestaltet werden. Innerhalb des Grid werden Zeilen- und Spaltenangaben gruppiert.
<Grid> <Grid.RowDefinitions> <RowDefinition></RowDefinition> <RowDefinition></RowDefinition> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition></ColumnDefinition> <ColumnDefinition></ColumnDefinition> </Grid.ColumnDefinitions> </Grid>
Innerhalb von Grid.RowDefinitions ist jede Zeile als eine RowDefinition gegeben, jede Spalte als ColumnDefinition im Abschnitt Grid.ColumnDefinitions. Bei der Aufteilung im Beispiel haben alle Zellen die gleiche Größe (siehe Abbildung 20.16). Bei Größenänderungen des Fensters bleiben die Größenverhältnisse der Zellen erhalten.
Abbildung 20.16 Grid im Designer von Visual Studio
Die Breite jeder einzelnen Spalte legen Sie mit der Eigenschaft Width fest. Analog setzt Height die Zeilenhöhe. Die Werte können Sie auf drei verschiedene Arten spezifizieren. Für feste Abmessungen machen Sie eine Angabe in Pixel. Die zweite Möglichkeit ist der Wert Auto. Damit wird die Spaltenbreite beziehungsweise Zeilenhöhe auf Basis des breitesten beziehungsweise höchsten Steuerelements bestimmt.
Das folgende Codefragment zeigt ein Grid mit zwei Zeilen und zwei Spalten. Die Spaltenbreite passt sich durch Auto automatisch an. In drei der vier Zellen ist je ein Button. Der Button links oben ist 200 Pixel breit, der links unten ist mit 100 Pixel halb so breit. Weil sich die Spalte an die Breite des größten Elements anpasst, ist der kleinere Button schmaler als die Spalte. Die Buttons der ersten Zeile sind zusammen breiter als das Fenster. Da sich durch Auto das Grid seinem Inhalt anpasst, ist es für das Fenster zu breit, und der Button oben rechts wird abgeschnitten (siehe Abbildung 20.17).
<Grid> <Grid.RowDefinitions> <RowDefinition></RowDefinition> <RowDefinition></RowDefinition> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"></ColumnDefinition> <ColumnDefinition Width="Auto"></ColumnDefinition> </Grid.ColumnDefinitions> <Button Grid.Column="0" Grid.Row="0" Width="200">Button1</Button> <Button Grid.Column="1" Grid.Row="0" Width="150">Button2</Button> <Button Grid.Column="0" Grid.Row="1" Width="100">Button3</Button> </Grid>
Abbildung 20.17 Automatische Spaltenbreite
In Abbildung 20.18 sehen Sie, was bei vollständigem Verzicht auf Auto passiert. Die Zellen sind alle gleich groß, aber zu klein für den Button oben links, der abgeschnitten wird.
Abbildung 20.18 Identische Zellengrößen
Mit der letzten Art einer Aufteilung spezifizieren Sie die Abmessung relativ zueinander. Gemessen wird in Einheiten des Wildcard-Zeichens *. Zum Beispiel ist Width="*" eine Einheit breit, Height="3*" ist drei Einheiten hoch. Eine Einheit ist gleich dem nach Abzug von Elementen fester Abmessungen verbleibenden Platz, dividiert durch die Summe aller *-Angaben. Zum Beispiel: Ein Gitter der Breite 400 Pixel hat die Spaltenbreiten *, 100, 2*, 3*. Der verbleibende Platz ist 300 Pixel, die Summe relativ bemaßter Spalten 6*. Damit ist eine *-Einheit 50 Pixel. Bei den Spalten *, 400, 2*, 3* haben die *-Spalten die Breite null. Da der Zahlenwert den Typ Double hat, können Sie bei Bedarf eine sehr genaue Aufteilung erzielen. Abbildung 20.19 zeigt den Fall *, 2*, 3*.
Abbildung 20.19 Relative Spaltenbreiten
Die Komponenten im Gitter werden innerhalb von Grid parallel zu Grid.RowDefinitions und Grid.ColumnDefinitions eingetragen. Die Attribute Grid.Column und Grid.Row geben den nullbasierten Spalten- bzw. Zeilenindex einer Komponente an. Fehlende Angaben werden durch null ersetzt, auch wenn dadurch Komponenten übereinander liegen.
Mit Angaben für Grid.ColumnSpan oder/und Grid.RowSpan können sich Komponenten über mehrere Spalten oder Zeilen erstrecken (siehe Abbildung 20.20). Die beiden Eigenschaften Grid.Column und Grid.Row geben dann die linke obere Zelle des Elements an.
<Grid> <Grid.RowDefinitions> <RowDefinition></RowDefinition> <RowDefinition></RowDefinition> <RowDefinition></RowDefinition> <RowDefinition></RowDefinition> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition></ColumnDefinition> <ColumnDefinition></ColumnDefinition> <ColumnDefinition></ColumnDefinition> </Grid.ColumnDefinitions> <Button Grid.Column="1" Grid.Row="1" Grid.ColumnSpan="2" Grid.RowSpan="2">Button1</Button> </Grid>
Abbildung 20.20 Mehrzellige Komponente
Zellengröße durch GridSplitter
Wenn der Anwender die Zeilenhöhe oder Spaltenbreite mit der Maus verändern darf, kann er das Gitter optimal für sich einstellen. Damit dies geht, braucht er eine Art »Griff« vom Typ GridSplitter. Er wird wie eine normale Komponente im Grid platziert und kann die benachbarten Zellen entlang seiner längeren Ausdehnung (Anzahl Zellen) in der Größe ändern (vertikal bei quadratischem Splitter). Machen Sie den Splitter sehr »dünn«, wird die Bedienung erschwert. Dies kann auch zur Laufzeit passieren, wenn die in Margins spezifizierten Ränder sehr schmal sind und der Splitter bis zum Anschlag bewegt wird.
Zur Beschleunigung können Sie ShowPreview auf den Wert True setzen. Gegenüber dem Standardwert False werden die Zellen dann nicht in Echtzeit angepasst, sondern es wird nur eine Kopie des Splitters bewegt, und erst beim Loslassen der Maustaste werden die Zellen angepasst.
Im folgenden Code ist ein vertikaler und ein horizontaler GridSplitter definiert, die in Abbildung 20.21 zu sehen sind. Mit den Eigenschaften Column, Row, ColumnSpan und RowSpan wird die Abmessung festgelegt. Die Ausrichtung, vertikal oder horizontal, ergibt sich aus der längeren Dimension.
<Grid> <Grid.RowDefinitions> <RowDefinition></RowDefinition> <RowDefinition></RowDefinition> <RowDefinition Height="15"></RowDefinition> <RowDefinition></RowDefinition> <RowDefinition></RowDefinition> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition></ColumnDefinition> <ColumnDefinition Width="20"></ColumnDefinition> <ColumnDefinition></ColumnDefinition> <ColumnDefinition></ColumnDefinition> </Grid.ColumnDefinitions> <Button Grid.Column="0" Grid.Row="0">Button1</Button> <Button Grid.Column="2" Grid.Row="1">Button2</Button> <Button Grid.Column="3" Grid.Row="3">Button3</Button> <Button Grid.Column="4" Grid.Row="4">Button4</Button> <GridSplitter ShowsPreview="True" Grid.Column="1" Grid.Row="0" Grid.RowSpan="3" HorizontalAlignment="Center" Margin="5,5,5,5" Width="3" /> <GridSplitter ShowsPreview="True" Grid.Row="2" Grid.ColumnSpan="3" HorizontalAlignment="Stretch" Margin="5,5,5,5" Height="3" /> </Grid>
Abbildung 20.21 GridSplitter zur Zellgrößenänderung
Ihre Meinung
Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de.