Przejdź do treści
School IT / Przestrzeń do nauki

Grid — wiersze i kolumny

Do tej pory układałeś kontrolki jedna pod drugą w StackPanel. Większość prawdziwych okien wygląda jednak jak tabela: napisy po lewej, pola po prawej, przyciski w rzędzie, a główna część rośnie razem z oknem. Do tego służy Grid — najważniejszy panel w WPF i ten sam, który od lekcji 01 czeka pusty w każdym nowym projekcie.

XAML C# Grid RowDefinitions Auto i * ColumnSpan 90 min
CEL LEKCJI

Czego się dziś nauczysz

  • Podzielisz okno na wiersze i kolumny za pomocą RowDefinitions i ColumnDefinitions.
  • Umieścisz kontrolkę w wybranej komórce właściwościami Grid.Row i Grid.Column.
  • Dobierzesz rozmiar wiersza lub kolumny: stały, Auto albo proporcjonalny * — i policzysz, ile miejsca dostanie kolumna 2*.
  • Połączysz kilka komórek w jedną przez Grid.ColumnSpan i Grid.RowSpan.
  • Zbudujesz okno, w którym główna część rośnie razem z oknem, a nagłówek i przyciski zostają na swoim miejscu.
  • Zagnieździsz jeden Grid w drugim i dodasz kontrolkę do komórki z kodu C#.
TEORIA

Wiersze, kolumny i numery komórek

Pusty <Grid> ma jedną komórkę na całe okno. Żeby go podzielić, najpierw opisujesz, ile ma wierszy i kolumn, a dopiero potem wstawiasz kontrolki:

MainWindow.xaml
<Grid>
    <Grid.RowDefinitions>          <!-- 2 wiersze -->
        <RowDefinition/>
        <RowDefinition/>
    </Grid.RowDefinitions>

    <Grid.ColumnDefinitions>       <!-- 3 kolumny -->
        <ColumnDefinition/>
        <ColumnDefinition/>
        <ColumnDefinition/>
    </Grid.ColumnDefinitions>

    <Button Grid.Row="0" Grid.Column="0" Content="A"/>
    <Button Grid.Row="0" Grid.Column="2" Content="B"/>
    <Button Grid.Row="1" Grid.Column="1" Content="C"/>
</Grid>

Jeden znacznik <RowDefinition/> to jeden wiersz, jeden <ColumnDefinition/> — jedna kolumna. Miejsce kontrolki podajesz w samej kontrolce: Grid.Row to numer wiersza, Grid.Column — numer kolumny. Numeracja zaczyna się od 0:

Row 0 · Col 0
A
Row 0 · Col 1
Row 0 · Col 2
B
Row 1 · Col 0
Row 1 · Col 1
C
Row 1 · Col 2

siatka 2 × 3 — przycisk bez Width i Height wypełnia całą komórkę

Dlaczego Grid.Row, a nie samo Row?

Przycisk nie ma własnej właściwości „wiersz” — przecież może stać w StackPanel, gdzie wierszy nie ma. To Grid „dokleja” kontrolce swoją informację. Taką właściwość nazywamy dołączoną (ang. attached property) i zapisujemy z nazwą panelu przed kropką.

Kontrolka bez Grid.Row i Grid.Column trafia do komórki (0, 0), bo 0 to wartość domyślna. Dwie kontrolki w tej samej komórce nakładają się — ta, która jest niżej w pliku, rysuje się na wierzchu. To najczęstsza przyczyna „zniknięcia” przycisku.

Linie pomocnicze

Dopisz <Grid ShowGridLines="True">, a po uruchomieniu zobaczysz przerywane granice komórek. Świetne do szukania błędów w układzie — w gotowym programie usuń ten atrybut.

TEORIA

Rozmiary: liczba, Auto i gwiazdka

Wysokość wiersza ustawiasz atrybutem Height, szerokość kolumny — atrybutem Width:

ZapisNazwaCo oznacza
Height="60"rozmiar stałyDokładnie 60 jednostek, niezależnie od okna i zawartości.
Height="Auto"według zawartościWiersz jest tak wysoki, jak jego najwyższa kontrolka. Dobre dla napisów, pól jednowierszowych i przycisków.
Height="*"proporcjaWiersz dostaje część pozostałego miejsca. 2* to dwie części, 3* — trzy. To wartość domyślna: <RowDefinition/> znaczy to samo co Height="*".

Jak WPF dzieli szerokość — krok po kroku

Siatka ma 600 jednostek szerokości i cztery kolumny:

MainWindow.xaml
<Grid.ColumnDefinitions>
    <ColumnDefinition Width="100"/>   <!-- stała -->
    <ColumnDefinition Width="Auto"/>  <!-- przycisk w tej kolumnie ma 80 szerokości -->
    <ColumnDefinition Width="*"/>
    <ColumnDefinition Width="2*"/>
</Grid.ColumnDefinitions>
KrokCo robi WPFWynik
1Przydziela kolumny o stałej szerokościkolumna 0 → 100
2Mierzy zawartość kolumn Autokolumna 1 → 80
3Liczy, ile zostało600 − 100 − 80 = 420
4Sumuje gwiazdki: * + 2*3 części, jedna część = 420 / 3 = 140
5Rozdaje częścikolumna 2 → 140, kolumna 3 → 280
100
Auto
80
*
140
2*
280

po poszerzeniu okna rosną tylko kolumny z gwiazdką — w proporcji 1 : 2

TEORIA

Łączenie komórek: ColumnSpan i RowSpan

Nagłówek na całą szerokość okna albo duży przycisk na dwa wiersze: podajesz komórkę startową oraz liczbę zajmowanych kolumn (Grid.ColumnSpan) lub wierszy (Grid.RowSpan). Kontrolka rozciąga się zawsze w prawo i w dół.

MainWindow.xaml
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition/>
        <RowDefinition/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition/>
        <ColumnDefinition/>
    </Grid.ColumnDefinitions>

    <!-- wiersz 0, od kolumny 0, zajmuje 2 kolumny -->
    <TextBlock Grid.Row="0" Grid.ColumnSpan="2" Text="Panel gracza" FontSize="20"/>

    <!-- kolumna 0, od wiersza 1, zajmuje 2 wiersze -->
    <Button Grid.Row="1" Grid.RowSpan="2" Content="START"/>

    <Button Grid.Row="1" Grid.Column="1" Content="Opcje"/>
    <Button Grid.Row="2" Grid.Column="1" Content="Wyjście"/>
</Grid>
Row 0 · ColumnSpan 2 → „Panel gracza”
Row 1 · RowSpan 2
START
Row 1 · Col 1
Opcje
Row 2 · Col 1
Wyjście

ColumnSpan łączy w poziomie, RowSpan w pionie

TEORIA

Co rośnie razem z oknem

W lekcji 07 pole wielowierszowe w StackPanel musiało dostać stałą wysokość. W Grid wystarczy postawić je w wierszu z gwiazdką — wtedy wypełnia całe wolne miejsce i rośnie, gdy użytkownik powiększa okno:

MainWindow.xaml
<Grid Margin="10">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>   <!-- tytuł: tyle, ile tekst -->
        <RowDefinition Height="*"/>      <!-- notatka: cała reszta -->
        <RowDefinition Height="Auto"/>   <!-- przycisk: tyle, ile przycisk -->
    </Grid.RowDefinitions>

    <TextBlock Grid.Row="0" Text="Notatka" FontSize="18" Margin="0,0,0,5"/>
    <TextBox Grid.Row="1" AcceptsReturn="True" TextWrapping="Wrap"
             VerticalScrollBarVisibility="Auto"/>
    <Button Grid.Row="2" Content="Zapisz" Width="100" Margin="0,10,0,0"
            HorizontalAlignment="Right"/>
</Grid>
Notatka–□✕
Notatka
Kupić zeszyt do matematyki…
Zapisz

powiększ okno — rośnie tylko pole notatki

Zasada praktyczna

Wiersze z napisami, polami jednowierszowymi i przyciskami — Auto. Główna część okna — *. Liczby stałe stosuj rzadko: przy większej czcionce tekst może się w nich nie zmieścić.

TEORIA

Grid w Gridzie i Grid z kodu

W komórce może stać dowolna kontrolka — także StackPanel albo kolejny Grid z własnymi wierszami i kolumnami. Panel wewnętrzny numeruje swoje komórki od nowa, od 0. Dzięki temu dużą siatkę dzielisz na kawałki, z których każdy ma prosty układ (tak jest zbudowany przykład tej lekcji).

Kontrolkę możesz też dodać do siatki z kodu — tak jak w lekcji 03 dodawałeś napisy do StackPanel. Właściwości dołączone ustawiasz wtedy metodami Grid.SetRow i Grid.SetColumn:

MainWindow.xaml.cs
// w XAML: <Grid x:Name="Plansza"> z 3 wierszami i 3 kolumnami
for (int w = 0; w < 3; w++)
{
    for (int k = 0; k < 3; k++)
    {
        Button pole = new Button { Content = $"{w},{k}", Margin = new Thickness(2) };
        Grid.SetRow(pole, w);       // to samo co Grid.Row="w" w XAML
        Grid.SetColumn(pole, k);    // to samo co Grid.Column="k"
        Plansza.Children.Add(pole);
    }
}

Odczyt działa w drugą stronę: Grid.GetRow(pole) zwraca numer wiersza kontrolki.

PRZYKŁAD

Zamek szyfrowy

Okno z klawiaturą numeryczną. Użytkownik wpisuje 4 cyfry, OK sprawdza kod, C czyści wyświetlacz. Po trzech błędnych próbach zamek się blokuje. Okno to siatka z trzema wierszami: wyświetlacz, klawiatura i komunikat. Klawiatura jest osobnym Grid 4 × 3 w środkowym wierszu — dzięki temu można ją zablokować jednym poleceniem.

Zamek szyfrowy–□✕
24
1
2
3
4
5
6
7
8
9
C
0
OK
Błędny kod. Pozostało prób: 2

po pierwszej błędnej próbie i wpisaniu dwóch nowych cyfr

MainWindow.xaml — pełny plik
<Window x:Class="Lekcja09.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Zamek szyfrowy" Height="460" Width="320"
        WindowStartupLocation="CenterScreen">

    <!-- Siatka zewnętrzna: wyświetlacz, klawiatura, komunikat -->
    <Grid Margin="10">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

        <TextBlock x:Name="Wyswietlacz" Grid.Row="0"
                   Margin="4" Padding="10"
                   Background="Black" Foreground="Lime"
                   FontSize="32" FontFamily="Consolas" TextAlignment="Right"/>

        <!-- Siatka wewnętrzna: klawiatura 4 × 3 w wierszu 1 -->
        <Grid x:Name="Klawiatura" Grid.Row="1">
            <Grid.RowDefinitions>
                <RowDefinition Height="*"/>
                <RowDefinition Height="*"/>
                <RowDefinition Height="*"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>

            <Button Grid.Row="0" Grid.Column="0" Content="1" Margin="4" FontSize="22" Click="Cyfra_Click"/>
            <Button Grid.Row="0" Grid.Column="1" Content="2" Margin="4" FontSize="22" Click="Cyfra_Click"/>
            <Button Grid.Row="0" Grid.Column="2" Content="3" Margin="4" FontSize="22" Click="Cyfra_Click"/>

            <Button Grid.Row="1" Grid.Column="0" Content="4" Margin="4" FontSize="22" Click="Cyfra_Click"/>
            <Button Grid.Row="1" Grid.Column="1" Content="5" Margin="4" FontSize="22" Click="Cyfra_Click"/>
            <Button Grid.Row="1" Grid.Column="2" Content="6" Margin="4" FontSize="22" Click="Cyfra_Click"/>

            <Button Grid.Row="2" Grid.Column="0" Content="7" Margin="4" FontSize="22" Click="Cyfra_Click"/>
            <Button Grid.Row="2" Grid.Column="1" Content="8" Margin="4" FontSize="22" Click="Cyfra_Click"/>
            <Button Grid.Row="2" Grid.Column="2" Content="9" Margin="4" FontSize="22" Click="Cyfra_Click"/>

            <Button Grid.Row="3" Grid.Column="0" Content="C" Margin="4" FontSize="22" Click="Wyczysc_Click"/>
            <Button Grid.Row="3" Grid.Column="1" Content="0" Margin="4" FontSize="22" Click="Cyfra_Click"/>
            <Button Grid.Row="3" Grid.Column="2" Content="OK" Margin="4" FontSize="22" Click="Ok_Click"/>
        </Grid>

        <TextBlock x:Name="Komunikat" Grid.Row="2"
                   Margin="4,10,4,0" FontSize="16" TextAlignment="Center"
                   Text="Wpisz 4-cyfrowy kod"/>
    </Grid>
</Window>
MainWindow.xaml.cs — pełny plik
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace Lekcja09;

public partial class MainWindow : Window
{
    private const string Kod = "2468";
    private const int LimitProb = 3;

    private int bledneProby = 0;

    public MainWindow()
    {
        InitializeComponent();
    }

    // Jedna metoda obsługuje wszystkie dziesięć cyfr
    private void Cyfra_Click(object sender, RoutedEventArgs e)
    {
        Button przycisk = (Button)sender;

        if (Wyswietlacz.Text.Length < 4)
        {
            Wyswietlacz.Text += przycisk.Content;
        }
    }

    private void Wyczysc_Click(object sender, RoutedEventArgs e)
    {
        Wyswietlacz.Text = "";
    }

    private void Ok_Click(object sender, RoutedEventArgs e)
    {
        if (Wyswietlacz.Text.Length < 4)
        {
            Komunikat.Text = "Kod musi mieć 4 cyfry";
            Komunikat.Foreground = Brushes.DarkOrange;
            return;
        }

        if (Wyswietlacz.Text == Kod)
        {
            Komunikat.Text = "Zamek otwarty!";
            Komunikat.Foreground = Brushes.Green;
            Klawiatura.IsEnabled = false;
            return;
        }

        bledneProby++;
        Wyswietlacz.Text = "";

        if (bledneProby >= LimitProb)
        {
            Komunikat.Text = "Zamek zablokowany";
            Komunikat.Foreground = Brushes.Red;
            Klawiatura.IsEnabled = false;   // cała siatka z przyciskami naraz
        }
        else
        {
            Komunikat.Text = $"Błędny kod. Pozostało prób: {LimitProb - bledneProby}";
            Komunikat.Foreground = Brushes.Red;
        }
    }
}

Co dzieje się po kolei

  • Zewnętrzny Grid ma trzy wiersze: Auto dla wyświetlacza, * dla klawiatury i Auto dla komunikatu. Po powiększeniu okna rosną tylko przyciski.
  • Klawiatura to drugi Grid w wierszu 1. Ma własne 4 wiersze i 3 kolumny, numerowane od 0 — przycisk „1” ma Grid.Row="0", choć cała klawiatura stoi w wierszu 1 okna.
  • Wszystkie wiersze i kolumny klawiatury mają *, więc przyciski są równe. Grid nie robi odstępów między komórkami — szczelinę 8 jednostek tworzą marginesy sąsiednich przycisków (4 + 4).
  • Dziesięć cyfr ma jedną metodę Cyfra_Click. Który przycisk kliknięto, mówi (Button)sender, a jego Content to cyfra do dopisania.
  • Ok_Click sprawdza najpierw, czy wpisano 4 cyfry. Krótszy kod nie zużywa próby.
  • Poprawny kod lub trzecia błędna próba ustawia Klawiatura.IsEnabled = false. Właściwość z lekcji 05 działa na panel i na wszystko, co w nim jest — dwanaście przycisków blokuje się naraz.
  • Stałe Kod i LimitProb są w jednym miejscu na górze klasy — zmiana kodu to zmiana jednej linii.

Sprawdź trzy rzeczy

  1. Dopisz ShowGridLines="True" do obu siatek i porównaj, gdzie przebiegają linie zewnętrznej, a gdzie wewnętrznej.
  2. Usuń Grid.Row="1" przy przycisku „5”. Przycisk trafi do wiersza 0 klawiatury i nałoży się na „2”, a w środku zostanie dziura.
  3. Zmień wysokość środkowego wiersza zewnętrznej siatki na Auto. Klawiatura skurczy się do wysokości przycisków, a po powiększeniu okna na dole zostanie puste miejsce.
ELEMENTY WBUDOWANE

Zestawienie elementów

ElementWartościCo robi
Grid.RowDefinitions, Grid.ColumnDefinitionslista definicjiIle znaczników RowDefinition / ColumnDefinition w środku — tyle wierszy / kolumn.
RowDefinition.Height, ColumnDefinition.Widthliczba, Auto, *, 2*Rozmiar wiersza / kolumny. Domyślnie *.
Grid.Row, Grid.Columnint, od 0Właściwości dołączone — wpisujesz je w kontrolce. Domyślnie 0.
Grid.RowSpan, Grid.ColumnSpanint, od 1Ile wierszy / kolumn zajmuje kontrolka od komórki startowej.
ShowGridLinesTrue / FalsePrzerywane linie komórek — tylko do szukania błędów.
Grid.SetRow(k, n), Grid.SetColumn(k, n)metodyUstawiają wiersz / kolumnę kontrolki z kodu.
Grid.GetRow(k), Grid.GetColumn(k)intOdczytują wiersz / kolumnę kontrolki.
CZĘSTE BŁĘDY

Zanim utkniesz

ZapisProblem
<Button Grid.Column="3"/> przy 3 kolumnachWPF nie zgłosi błędu — po cichu wstawi przycisk do ostatniej kolumny (2), gdzie nałoży się na inny. Kolumny mają numery 0, 1, 2.
<Button Row="1"/>Błąd XAML: The property 'Row’ was not found. Potrzebny przedrostek: Grid.Row.
<RowDefinition Grid.Row="1"/>Definicja tylko opisuje rozmiar. Numer wiersza wpisujesz w kontrolce.
napis i pole bez Grid.Row/Grid.ColumnOba w komórce (0, 0) — pole zasłania napis.
Height="*2"Błąd XAML. Liczba stoi przed gwiazdką: 2*.
Grid.ColumnSpan="0"Błąd przy uruchomieniu — kontrolka zajmuje co najmniej jedną kolumnę.
wszystkie wiersze AutoNic nie rośnie z oknem. Po powiększeniu na dole zostaje puste miejsce.
przycisk z Width w komórce *Nie wypełni komórki, bo szerokość podałeś sam. Do wypełniania usuń Width.
ZADANIA

Zadania

Każde zadanie wykonaj w nowym projekcie Aplikacja WPF, chyba że treść mówi inaczej. Główny układ okna buduj na Grid. Wskazówkę otwórz dopiero wtedy, gdy utkniesz.

ZAD 1Panel windy★☆☆

Panel windy w ośmiopiętrowym budynku: u góry wyświetlacz z bieżącym piętrem (na start „0”), pod nim przyciski pięter 0–7 w siatce 4 wiersze × 2 kolumny, a na dole napis z komunikatem. Po kliknięciu piętra komunikat mówi „Jadę w górę na piętro 5” albo „Jadę w dół na piętro 2”, a wyświetlacz pokazuje nowe piętro. Kliknięcie piętra, na którym winda już jest, daje „Jesteś na piętrze 3”. Wszystkie piętra obsługuje jedna metoda.

Winda–□✕
5
6
7
4
5
2
3
0
1
Jadę w górę na piętro 5
pokaż wskazówkę
  • Bieżące piętro trzymaj w polu klasy typu int.
  • Numer klikniętego piętra odczytasz z Content przycisku — to object, więc zamień go przez int.Parse(przycisk.Content.ToString()). Tu dane wpisałeś sam w XAML, więc Parse jest bezpieczne.
ZAD 2Dziennik lektur★☆☆

Okno do notatek z lektury: u góry w jednym wierszu napis „Tytuł:” i pole na tytuł (pole zajmuje całą resztę szerokości). Pod spodem duże pole wielowierszowe na notatkę, które rośnie razem z oknem w obu kierunkach. Na dole po lewej napis „Znaków: 0” aktualizowany przy każdej zmianie notatki, a po prawej przycisk Wyczyść, który czyści oba pola.

pokaż wskazówkę
  • Zastanów się, które wiersze mają być Auto, a który *. W pierwszym wierszu napis i pole stoją w dwóch kolumnach — jakie szerokości?
  • Notatka i dolny wiersz muszą zająć wszystkie kolumny.
ZAD 3Informator szkolny★★☆

Klasyczny układ aplikacji: nagłówek „Informator ZSMI” na całą szerokość (wysokość według tekstu, ciemne tło), po lewej kolumna menu z przyciskami Godziny dzwonków, Sekretariat, Biblioteka, Stołówka, po prawej obszar treści 3 razy szerszy od menu, a na dole stopka o stałej wysokości 30 z napisem „Wybrano: Biblioteka”. Kliknięcie przycisku menu wpisuje do obszaru treści informacje o wybranym miejscu (wymyśl je) i zmienia stopkę.

Informator–□✕
Informator ZSMI
Godziny dzwonków
Sekretariat
Biblioteka
Stołówka
Biblioteka szkolna
pon.–pt. 8:00–15:00
sala 104, I piętro
Wybrano: Biblioteka
pokaż wskazówkę
  • Siatka 3 × 2. Proporcja „3 razy szersza” to zapis z gwiazdkami. Nagłówek i stopka zajmują obie kolumny.
  • Przyciski menu ułóż w StackPanel postawionym w jednej komórce. Treść dla każdego przycisku możesz trzymać w jego Tag.
ZAD 4Zamek z gwiazdkami★★☆

Rozbuduj przykład. Wyświetlacz ma pokazywać gwiazdki zamiast cyfr (po 3 cyfrach: ***), a sprawdzanie kodu ma działać jak wcześniej. Dodaj pod klawiaturą przycisk ← Usuń cyfrę na całą szerokość okna, który usuwa ostatnią wpisaną cyfrę (przy pustym kodzie nic nie robi). Po otwarciu zamka pokaż przycisk Zamknij ponownie, który zeruje licznik prób i odblokowuje klawiaturę.

pokaż wskazówkę
  • Wyświetlacz nie może już przechowywać kodu — cyfry trzymaj w polu klasy typu string. Gwiazdki: new string('*', liczba).
  • Nowy wiersz siatki zmienia numer wiersza komunikatu. Usunięcie ostatniego znaku: Substring(0, długość - 1).
  • Przycisk „Zamknij ponownie” może od początku stać w oknie z Visibility="Collapsed".
ZAD 5Tabliczka mnożenia★★☆

Okno z pustym Grid o 11 wierszach i 11 kolumnach (wszystkie *). Po otwarciu okna program wypełnia go z kodu: w wierszu 0 i kolumnie 0 liczby 1–10 na szarym tle (nagłówki), w pozostałych komórkach iloczyny. Kwadraty liczb (na przekątnej) mają żółte tło. Komórki to TextBlock z tekstem wyśrodkowanym. Okno ma rozmiar 500 × 500, a po jego powiększeniu komórki rosną równo.

pokaż wskazówkę
  • Dwie zagnieżdżone pętle od 0 do 10 i Grid.SetRow/Grid.SetColumn dla każdego napisu. Komórkę (0, 0) zostaw pustą.
  • Iloczyn w komórce (w, k) to w * k. Kwadrat — gdy w == k.
  • Wiersze i kolumny możesz zapisać w XAML — kodem dodajesz tylko napisy.
ZAD 6Kółko i krzyżyk★★★

Plansza 3 × 3 z dziewięciu pustych przycisków (czcionka 40), pod nią napis „Ruch: X” i przycisk Nowa gra. Kliknięcie wolnego pola wstawia na zmianę X i O, kliknięcie zajętego nic nie zmienia. Po każdym ruchu program sprawdza 8 linii (3 wiersze, 3 kolumny, 2 przekątne). Przy wygranej pokazuje „Wygrywa X!” i blokuje planszę, przy zapełnionej planszy bez zwycięzcy — „Remis”. Prowadź też wynik meczu: „X: 2   O: 1   remisy: 1”. Wszystkie pola obsługuje jedna metoda.

pokaż wskazówkę
  • Planszę połóż w osobnym Grid z nazwą — łatwo ją wtedy zablokować i przejść po polach przez Children.
  • Pola nazwij P0–P8 i w konstruktorze zbierz je w tablicę Button[]. Linie zapisz jako tablicę trójek indeksów, np. { 0, 4, 8 }.
  • Wolne pole ma Content równe null.
PODSUMOWANIE

Co trzeba zapamiętać

  • Wiersze i kolumny opisujesz w Grid.RowDefinitions i Grid.ColumnDefinitions.
  • Miejsce ustawiasz w kontrolce: Grid.Row, Grid.Column. Numeracja od 0, domyślnie 0.
  • Liczba = rozmiar stały, Auto = według zawartości, * = część pozostałego miejsca. * i 2* dzielą resztę w proporcji 1 : 2.
  • Grid.ColumnSpan i Grid.RowSpan rozciągają kontrolkę w prawo i w dół.
  • Napisy i przyciski w wierszach Auto, główna część w wierszu * — wtedy okno dobrze się skaluje.
  • Siatki można zagnieżdżać; z kodu komórkę ustawiasz przez Grid.SetRow i Grid.SetColumn.

Dokumentacja: Microsoft Learn — Grid.

Postęp zapisuje się w tej przeglądarce.