Grid

7. díl - Grid

Tomáš Jecha, MVP, MCSD       16.03.2012       C#, VB.NET, WPF, Komponenty, .NET       19163 zobrazení

Grid je jedna z nejdůležitější a nejpoužívanějších pozicovacích komponent ve WPF. Ulehčuje návrh formulářů a své uplatnění nachází v řadě scénářů.

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:

WPF Grid - designer

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:

image

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.

WPF Grid 1

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>

WPF Grid 2

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.

 

hodnocení článku

2 bodů / 2 hlasů       Hodnotit mohou jen registrované uživatelé.

 

 

 

Nový příspěvek

 

Diskuse: Grid

Dobry den Tomasi,

Najprv by som rad podakoval za vsetky clanky - len mi je trochu luto, ze som na ne narazil az teraz a nie hned na zaciatku :)

U WPF mi vyslovene vadi len jedina vec a to su prave indexy u Row\Column - bohuzial sa tu neda pouzivat odkaz napriklad pomocou .Name, takze mi to pride hodne katastrofalne a prepisovat trosku zlozitejsi XAML (ked clovek potrebuje narvat tlacitko do existujuceho row\column) je vyslovene utrpenim...

Nema s tym problem nikto okrem mna? :)

Martin

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Dobrý den,

to je poměrně běžný požadavek, který se dá celkem snadno řešit. Já osobně jsem si napsal vlastní Grid, který umožňuje vkládání automatických řádků bez nutnosti zapisovat RowIndex. Kód poskytnout nemohu, ale doporučuji se podívat například na: http://wpfcontrib.codeplex.com/wikipage?...

Sám tuto komponentu nevyužívám, ale minimálně vás správně nasměruje.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Dobry den Tomasi,

To bohuzial ale prilis nepomoze ked je n rows a n columns :)

Ja to riesim tak, ze mam napisany MarkupExtensionReturnType, takze v XAML mozem pouzivat priamo names <Grid Grid.Row="{local:GetRowID Row_Main}">

Ale stale to nie je uplne ono (samozrejme hlavne kvoli tomu, ze designer to nezvladne...

Ak mate dopredu naplanovanu nejaku osnovu na dalsie clanky, velmi rad by som uvital dve kapitoly - zaludnosti WPF (viz. napriklad indexing u grid) a nejake doporucenia ako prejst v WinForms.

Este raz diky za super clanky!

Martin

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Diskuse: Grid

Ve Visual studiu 2010 expres komponenta Grid není. Je to nedostatek edice expres nebo je v této verzi nahrazena něčím jiným. Děkuji za odpověď

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Grid je k dispozici ve všech verzích .NET Frameworku podporujících WPF (od .NET 3.0). Nemluvíte náhodou o DataGrid pro zobrazování dat?

Pravděpodobně máte projekt založený pro .NET 3.5. Pokud jej založíte pro .NET 4, komponentu Grid budete mít k dispozici.

Pro .NET 3.5 není DataGrid v základní sadě komponent. Nicméně můžete využít WPF Toolkit (http://wpf.codeplex.com/ ), což je knihovna komponent obsahujících mimo jiných i DataGrid. Každopádně, pokud máte tu možnost, doporučuji využít odladěnější a propracovanější komponenty z .NET 4.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Hledal jsem komponentu Grid, ale přesto že mám nastaven .NET 4 tak jediné podobné je TableLayoutPanel. Děkuji za odpověď

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Už jsem Grid našel. Je třeba při zakládání nového projektu zvolit WPF Application a ne Windows Form application.

nahlásit spamnahlásit spam -3 / 3 odpovědětodpovědět

Diskuse: Grid

Dobrá práce, děkuji za tento seriál...

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Diskuse: Grid

Díky za skvělý článek, pozicování je ve WPF opravdu luxusní ve srovnání s WinForms, již žádné problémy s DPI, případně rozlišením obr.

nahlásit spamnahlásit spam 3 / 3 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.

Nyní zakládáte pod článkem nové diskusní vlákno.
Pokud chcete reagovat na jiný příspěvek, klikněte na tlačítko "Odpovědět" u některého diskusního příspěvku.

Nyní odpovídáte na příspěvek pod článkem. Nebo chcete raději založit nové vlákno?

 

  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:
Heslo:

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback