Grid je pozicovací komponenta. Sama o sobě nemá žádný vzhled a stará se “jen” o rozdělení prvků do pomyslné mřížky, jejímž sloupcům a řádkům lze jednoduše, ale zároveň efektivně nastavovat způsob výpočtu šířky a výšky.
Pokud neuvedeme definici ani pro jeden sloupec, je celý Grid na svoji šířku jedním sloupcem. Stejně toto platí i pro řádky. Pokud neuvedeme ani jednu definici řádku, je celý Grid na svoji výšku jedním řádkem. To je důvod, proč můžeme do Gridu vkládat další komponenty i bez jakéhokoliv nastavování sloupců, či řádků a používat jej i jako primitivní panel.
Panel
Grid podobně jako řada dalších pozicovacích komponent (StackPanel, Canvas, DockPanel a další) dědí z abstraktní třídy Panel. Ta zajišťuje základní funkce pro komponenty, které mají za úkol se starat o rozložení komponent uvnitř sebe sama.
Možnosti samotné třídy Panel třídy jsou obrovské a hojně se používá ke zpracování vlastních rozložení. Lze využít prakticky ke všem návrhům, kdy je potřeba nějakým speciálním způsobem pozicovat elementy a nestačí na to základní sada komponent. Není to úplně běžné a ne vždy je to nutné, pokud to však potřebujete, jde to. Příkladem může být vytváření tag-cloudu nebo zobrazení fotek v nějakém nestandardním rozložení (pověšené na šňůře, naházené na hromadu a další designové obskurnosti), či vytváření vlastních rozložení, jako je tomu například u ovládacího menu Office – Ribbon.
Nastavení Gridu
Při práci s Grid komponentou rozdělujete ovládací prvky do sloupců a řádků. K definování se používají vlastnosti:
- Vlastnost ColumnDefinitions – definice sloupců – kolekce ColumnDefinition objektů
- Vlastnost RowDefinitions – definice řádků – kolekce RowDefinition objektů
Základní nastavení šířky sloupců a výšky řádků
Asi nejdůležitější hodnotou je u definice sloupce ColumnDefinition jeho šířka Width. A u definice řádku RowDefinition jeho výška Height.
Takže například definice dvou řádků a tří sloupců může vypadat takto (použité vlastnosti vysvětlím v následujících odstavcích):
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition Height="*" MinHeight="20" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" MinWidth="50" />
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
</Grid>
U každého řádku nebo sloupce lze velikost nastavit několik variant hodnot. Konkrétně tyto tři:
- Absolutní
- Automatická
- Výplň
Nyní jednotlivé možnosti proberu.
Absolutní velikost
Použití absolutní velikosti je zcela identické jako při nastavování absolutní velikosti běžných elementů. Do hodnoty zapíšete číslo, které bude vzato jako absolutní šířka sloupce nebo výška řádku.
Tento jednoduchý příklad ukazuje, jak nadefinovat Grid se dvěma řádky o velikosti 50 a 80 device independent pixels:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition Height="80" />
</Grid.RowDefinitions>
</Grid>
Automatická velikost
Stejně jako absolutní velikost, i automatická velikost je při nastavování shodná s nastavováním automatické velikosti u běžných elementů. Zapisujeme ji tedy jako hodnotu Auto. To zajišťuje, že buňka bude široká / vysoká tolik, kolik bude vyžadovat její obsah.
Následující příklad ukazuje, jak nadefinovat 2 sloupce, kde první bude mít absolutní pevnou šířku 150 a druhý bude mít šířku automatickou dle jeho obsahu:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
</Grid>
Velikost typu “výplň”
Posledním typem velikost je “výplň”. Pokud takto označíte některý ze sloupců, či řádků, bude jejich šířka, či výška, vyplňovat zbývající místo v Gridu. Tato hodnota se zapisuje pomocí znaku hvězdičky *.
Příklad ukazuje, jak zapsat definici, kde má první a druhý řádek pevnou, třetí automatickou velikost podle svého obsahu a poslední, čtvrtý vyplňuje zbývající část Gridu:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="40" />
<RowDefinition Height="150" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
</Grid>
Definic s “hvězdičkou” lze zapsat i více. Volné místo se pak poměrově rozdělí mezi ně. Pokud bude tedy zbývat v Gridu na šířku 90 device-independent-pixels a budou nedeklarovány 3 sloupce se šířkou *, každý z nich bude široký 30 device-independent-pixels.
Pokud chcete poměr mezi sloupci změnit, lze doplnit před znak hvězdičky číslo určující poměr proti ostatním. Pokud číslo neuvedeme, bere se tento poměr jako 1*. Dále uvedený kód definuje 3 řádky, kde první a poslední jsou stejně veliké a prostřední je 2× větší:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" /><!-- 25% -->
<RowDefinition Height="2*" /><!-- 50% -->
<RowDefinition Height="*" /><!-- 25% -->
</Grid.RowDefinitions>
</Grid>
Minimální a maximální velikost
U definice řádku i sloupce lze nastavit minimální a maximální velikost. U definice sloupců ColumnDefinition jsou to vlastnosti MinWidth (minimální šířka) a MaxWidth (maximální šířka). U definice RowDefinition zase logicky MinHeight (minimální výška) a MaxHeight (maximální výška).
Tento kód definuje 2 řádky, která budou poměrem 1:1 vyplňovat celou výšku Gridu. Zároveň bude zajištěno, že spodní řádek bude vysoký alespoň 50 device-independent-pixels.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" MinHeight="50" />
</Grid.RowDefinitions>
</Grid>
Zobrazení v designéru
Užitečnou pomůckou při návrhu je designér. Pro jeho použití je důležité objekt Grid nejprve označit. To lze udělat jak přímo z designéru, tak i v XAML kódu zvolením požadovaného elementu Grid. Po takovém vybraní se znázorní jednotlivé sloupce a řádky. V jejich záhlaví je navíc vidět malým písmem hodnota vlastnosti Width pro sloupce nebo Height pro řádky:
Při najetí na hlavičku sloupce nebo řádku se otevře menu, kde může změnit typ velikosti sloupce. Z leva to je absolutní velikost, výplň (hvězdička) a automatická velikost:
A pokud vám z nějakého důvodu nevyhovuje zapisování definicí do kódu, je možné kliknutím do záhlaví nový sloupec nebo řádek přidat přímo z designéru.
Vkládání obsahu
Pokud do Gridu vložíte obsah a nenastavíte mu žádnou doplňující vlastnost, vždy bude daný obsah vložen do prvního sloupce, prvního řádků. To oceníte, pokud využíváte Grid jen jako jednoduchý kontejner na objekty a nechcete rozdělení na sloupce a řádky vůbec řešit.
Pro změnu sloupce nebo řádku, kam vnořený element patří, využijete vlastnosti “Grid.Column” a “Grid.Row”, kterou lze nastavit na všech elementech pořadové číslo sloupce nebo řádku (číslujeme od 0 pro první sloupec/řádek). Následující příklad ukazuje Grid rozdělený na 4 buňky (2 sloupce a 2 řádky), kde každá buňka obsahuje obarvený nápis:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label Background="LightYellow" Content="Sloupec vlevo nahoře" />
<Label Background="LightCoral" Content="Sloupec vpravo nahoře" Grid.Column="1" />
<Label Background="LightGreen" Content="Sloupec vlevo dole" Grid.Row="1" />
<Label Background="LightSkyBlue" Content="Sloupec vpravo dole" Grid.Row="1" Grid.Column="1" />
</Grid>
Poznámka: U elementů, které spadají do prvního sloupce nebo řádku nemusím explicitně nastavovat Grid.Column=”0” a Grid.Row=”0”. Pokud to však například kvůli přehlednosti chcete udělat, nic tím nezkazíte.
Výsledek zobrazuje 4 stejně veliké dlaždice, které si poměr velikostí drží i při změnách velikosti okna.
Poznámka: Vlastnosti Grid.Column a jí podobné nad elementy ve skutečnosti neexistují (například Label nemá vlastnost Grid.Column). Byly přidány dodatečně pomocí tzv. attached properties. Ty dovolují k existujícím komponentám přidávat další externí vlastnosti, ke kterým lze přistupovat v XAML kódu přímo, jako kdyby fyzicky existovaly nad třídou, se kterou pracujeme. Tomuto tématu se budu věnovat v dalších kapitolách. Pro začínající uživatele WPF je ale zbytečné se tímto zatím zaobírat.
ColumnSpan a RowSpan
Pomocí vlastností Grid.ColumnSpan a Grid.RowSpan můžete elementy nechat přetékat přes více buněk najednou. Toto nastavení je ve výchozím stavu na hodnotě 1 – tedy element zasahuje pouze do jedné buňky.
Například změnou Grid.ColumnSpan na hodnotu 2 můžete u předchozího příkladu nechat přetéct element skrz oba sloupce:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label Background="LightYellow" Content="Sloupec vlevo nahoře" Grid.ColumnSpan="2" />
<Label Background="LightGreen" Content="Sloupec vlevo dole" Grid.Row="1" />
<Label Background="LightSkyBlue" Content="Sloupec vpravo dole" Grid.Row="1" Grid.Column="1" />
</Grid>
Závěr
Tímto jsem pokryl základy nastavení a použití prvku Grid. V jednom z dalších dílů se budu věnovat pokročilejším funkcím použití (sdílená velikost sloupců mezi několika Gridy) a častým postupům při vnořování pozicovacích komponent.