Grafikus C# – Windows Forms tanfolyam › 15.2 lecke

Továbbtanulás · 15.2 lecke · WPF

Bevezetés az XAML-be

A WPF felületét XAML írja le (kiejtése: „zamel”). Ha ismered a HTML-t vagy az XML-t, a XAML ismerős lesz: elemek, attribútumok, egymásba ágyazott szerkezet. A különbség az, hogy a XAML C# objektumokat hoz létre: minden elem egy .NET osztály példánya, minden attribútum egy tulajdonság. Ebben a leckében megtanulod a XAML felépítését, az elrendezés-paneleket (Grid, StackPanel, DockPanel, WrapPanel), a távolságok kezelését (Margin, Padding), a legfontosabb vezérlőket, valamint az erőforrásokat és stílusokat, amelyekkel az egész program kinézetét egy helyről irányíthatod.

  • kb. 100 perc
  • közepes szint
  • XAML
Diáklány C# programot készít laptopon

A lecke végére

  • olvasod és írod a XAML szerkezetét (elemek, attribútumok, névterek, x:Name);
  • tudod, hogy a XAML elem egy C# objektum, és hogyan felel meg a kódnak;
  • használod az elrendezés-paneleket: Grid, StackPanel, DockPanel, WrapPanel;
  • helyesen állítod a Margin, Padding, HorizontalAlignment, Width értékeit;
  • ismered a leggyakoribb vezérlőket;
  • erőforrást és stílust definiálsz (Style, Setter, Trigger), és alkalmazod az egész programra.

Mielőtt elkezded

Ehhez a leckéhez a 15.1 lecke (Windows Forms és WPF összehasonlítása) szükséges. Új WPF projekt: Visual Studio → WPF Application (vagy dotnet new wpf).

15.1 WPF összehasonlítás →

A XAML felépítése

MainWindow.xamlXAML
<!-- x:Class: a hozzátartozó C# osztály (code-behind); az első xmlns: az alap WPF elemek névtere; -->
<!-- az xmlns:x az x: előtagú XAML-elemek (x:Name, x:Class); a Title, Height, Width tulajdonságok attribútumként -->
<Window x:Class="Urlap.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Űrlap" Height="300" Width="400">

<StackPanel Margin="16"> <!-- a Window egyetlen gyereke (tartalma) -->
<TextBlock Text="Név:"/> <!-- önzáró elem: <... /> -->
<TextBox x:Name="txtNev"/> <!-- x:Name: a code-behindban elérhető -->
<Button Click="Mentes_Click"> <!-- esemény: a kezelő neve -->
<StackPanel Orientation="Horizontal"> <!-- a gomb tartalma BÁRMI lehet -->
<TextBlock Text="💾 "/>
<TextBlock Text="Mentés"/>
</StackPanel>
</Button>
</StackPanel>
</Window>
Ugyanez C# kódból (csak a megértéshez)C#
StackPanel panel = new StackPanel { Margin = new Thickness(16) };

panel.Children.Add(new TextBlock { Text = "Név:" });

txtNev = new TextBox();
panel.Children.Add(txtNev);

Button gomb = new Button { Content = "Mentés" };
gomb.Click += Mentes_Click;
panel.Children.Add(gomb);

this.Content = panel; // az ablak tartalma
Elem = objektum, attribútum = tulajdonságA <Button Content="Mentés"/> egy new Button { Content = "Mentés" } kifejezéssel egyenértékű. A XAML tehát nem külön nyelv a logikához: csak a felület objektumainak kényelmes, olvasható leírása.
NévterekAz xmlns megmondja, honnan jönnek az elemnevek. Az első (presentation) a WPF vezérlői (Button, Grid), az x: előtagú a XAML saját elemei (x:Name, x:Class, x:Key). A saját osztályaidat az xmlns:ujNev="clr-namespace:Urlap" formában vonhatod be.
Tartalom-modellA Windownak és a legtöbb vezérlőnek (Button) egyetlen tartalma van, de az bármi lehet: szöveg, kép, vagy egy panel több elemmel. Ezért kell az ablak egyetlen gyerekeként egy panel (Grid/StackPanel), amely a többit tartalmazza.
XML-szabályokA XAML valódi XML: minden elemet le kell zárni, az attribútumok idézőjelben vannak, a & jelet & alakban, a < jelet < alakban kell írni. A megjegyzés <!-- ... -->.

Jósolj!

A Window alá két panelt írsz közvetlenül egymás mellé (<StackPanel/><StackPanel/>) egy közös szülő nélkül. Mi történik fordításkor?

Jóslat ellenőrzése

Fordítási hiba: a Window tartalma csak egyetlen elem lehet („The property 'Content' is set more than once”). A két panelt egy közös Grid-be vagy StackPanel-be kell tenni.

Az elrendezés-panelek

PanelHogyan rendezi az elemeit?Mikor?
StackPanelEgymás alá (Vertical, alap) vagy egymás mellé (Horizontal).Egyszerű lista, gombsor.
GridSorok és oszlopok rácsa; Grid.Row, Grid.Column, RowSpan, ColumnSpan.Űrlap, összetett ablak: a legsokoldalúbb.
DockPanelElemek a szélekhez (DockPanel.Dock="Top/Bottom/Left/Right"), az utolsó kitölti a maradékot.Menüsor, állapotsor, oldalsáv + tartalom.
WrapPanelSorban/oszlopban, és tördel, ha elfogy a hely.Kártyák, ikonok, címkék.
CanvasAbszolút (X, Y) pozíció: mint a Windows Forms.Rajz, játék; általános felülethez ne.
Grid űrlap: címkék és mezőkXAML
<Grid Margin="16">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/> <!-- a legszélesebb elem szélessége (a címkék oszlopa) -->
<ColumnDefinition Width="*"/> <!-- a maradék hely: a mezők kitöltik -->
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/> <!-- a maradék függőleges hely -->
</Grid.RowDefinitions>

<TextBlock Grid.Row="0" Grid.Column="0" Text="Név:" VerticalAlignment="Center" Margin="0,0,8,8"/>
<TextBox Grid.Row="0" Grid.Column="1" Margin="0,0,0,8"/>
<TextBlock Grid.Row="1" Grid.Column="0" Text="E-mail:" VerticalAlignment="Center" Margin="0,0,8,8"/>
<TextBox Grid.Row="1" Grid.Column="1" Margin="0,0,0,8"/>
<Button Grid.Row="2" Grid.Column="1" Content="Mentés" HorizontalAlignment="Right" VerticalAlignment="Top"/>
</Grid>

<!-- DockPanel: menü fent, állapotsor lent, a tartalom kitölti a közepét -->
<DockPanel>
<Menu DockPanel.Dock="Top">...</Menu>
<StatusBar DockPanel.Dock="Bottom">...</StatusBar>
<TextBox AcceptsReturn="True"/> <!-- az utolsó elem kitölti a maradékot (LastChildFill) -->
</DockPanel>
Méretezés a GridbenA sor/oszlop mérete háromféle lehet: Auto (az elemek mérete szerint), * (a maradék hely arányosan: 2* kétszer annyit kap, mint *), vagy fix szám (pixelben, DPI-független). Az űrlapnál tipikus: Auto a címkéknek, * a mezőknek.
Margin és PaddingA Margin az elem külső távolsága a szomszédoktól, a Padding a belső távolság a tartalom előtt. Értéke: egy szám (mind a négy oldal), kettő (vízszintes,függőleges) vagy négy (bal,fent,jobb,lent): Margin="0,0,8,8".
IgazításA HorizontalAlignment (Left, Center, Right, Stretch) és VerticalAlignment a cellában/panelben igazít. A Stretch az alap: az elem kitölti a rendelkezésre álló helyet. Fix Width/Height helyett inkább MinWidth, MaxWidth, és hagyd a panelt méretezni.
LáthatóságA Visibility értéke Visible, Hidden (nem látszik, de a helyét foglalja) vagy Collapsed (nem látszik, és nem foglal helyet): a feltételes megjelenítés alapja.

Jósolj!

A Grid-ben három oszlop van: Width="*", Width="2*", Width="100". Az ablak 700 egység széles (margó nélkül). Mekkora a három oszlop?

Jóslat ellenőrzése

A fix oszlop 100; a maradék 600 oszlik 1 : 2 arányban: 200 és 400. Az ablak átméretezésekor a fix oszlop marad, a csillagosak arányosan nőnek/csökkennek.

A leggyakoribb vezérlők

WPF vezérlőWindows Forms megfelelőjeMegjegyzés
TextBlockLabelCsak megjelenít szöveget (Text), egyszerű és könnyű.
LabelLabelTartalma (Content) bármi; hozzáférési billentyű (_Név).
TextBoxTextBoxText, AcceptsReturn (többsoros), TextWrapping.
ButtonButtonContent (nem Text), IsDefault, IsCancel.
CheckBox, RadioButtonugyanazIsChecked (bool?: lehet null is).
ComboBox, ListBoxugyanazItemsSource (kötés), SelectedItem, elemek bármilyen tartalommal.
Slider, ProgressBarTrackBar, ProgressBarMinimum, Maximum, Value.
ImagePictureBoxSource="Kepek/logo.png", Stretch.
DataGridDataGridViewItemsSource kötéssel, oszlopok automatikus vagy kézi.
Vezérlők együtt (XAML részlet)XAML
<StackPanel Margin="16">
<TextBlock Text="Regisztráció" FontSize="22" FontWeight="Bold" Margin="0,0,0,12"/>

<Label Content="_Név:" Target="{Binding ElementName=txtNev}"/> <!-- Alt+N a mezőre ugrik -->
<TextBox x:Name="txtNev" Margin="0,0,0,8"/>

<CheckBox x:Name="chkHirlevel" Content="Hírlevelet kérek" IsChecked="True" Margin="0,0,0,8"/>

<ComboBox x:Name="cmbOsztaly" SelectedIndex="0" Margin="0,0,0,8">
<ComboBoxItem Content="9.A"/>
<ComboBoxItem Content="9.B"/>
<ComboBoxItem Content="10.A"/>
</ComboBox>

<Slider x:Name="sldKor" Minimum="10" Maximum="20" Value="15" TickFrequency="1" IsSnapToTickEnabled="True"/>
<TextBlock Text="{Binding Value, ElementName=sldKor, StringFormat=Életkor: {0}}"/> <!-- adatkötés: a következő leckében részletezzük -->

<Button Content="Mentés" IsDefault="True" Click="Mentes_Click" Margin="0,12,0,0" HorizontalAlignment="Right" Padding="16,6"/>
</StackPanel>
TextBlock és TextBoxA TextBlock csak megjelenít, a TextBox szerkeszthető. A Windows Forms Label megfelelője a TextBlock (Text), nem a WPF Label (Content, kicsit nehezebb, hozzáférési billentyűvel).
A tartalom bármi lehetA Button, Label, ListBoxItem tartalma nem csak szöveg: lehet kép, többsoros panel, akár másik vezérlő. Ezért a WPF vezérlőinek tulajdonsága a Content, és nincs Text.
Kódból elérésAz x:Name adja a code-behindban elérhető nevet (txtNev.Text, chkHirlevel.IsChecked). A CheckBox.IsChecked típusa bool?: az érték true, false vagy null (három állapotú is lehet): if (chk.IsChecked == true).
EseményekA WPF eseményei átbuborékolnak a vizuális fán (routed events): a gomb Click eseménye RoutedEventArgs paramétert kap. A kezelő neve a Click="Mentes_Click" attribútumban, a metódus a code-behindban: private void Mentes_Click(object sender, RoutedEventArgs e).

Jósolj!

Egy CheckBox IsChecked értékét így olvasod: if (chk.IsChecked) { ... }. Mi történik fordításkor?

Jóslat ellenőrzése

Fordítási hiba (CS0266/CS0029): az IsChecked típusa bool?, nem bool, ezért az if nem fogadja el. Helyesen: if (chk.IsChecked == true).

Erőforrások, stílusok és triggerek

App.xaml: az egész programra érvényes erőforrásokXAML
<Application x:Class="Urlap.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
<Application.Resources>

<!-- színek és ecsetek: egy helyen, névvel -->
<SolidColorBrush x:Key="FoSzin" Color="#6840A5"/>
<SolidColorBrush x:Key="KiemeltSzin" Color="#8B60BA"/>

<!-- IMPLICIT stílus: minden Button erre vonatkozik (nincs x:Key) -->
<Style TargetType="Button">
<Setter Property="Background" Value="{StaticResource FoSzin}"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="Padding" Value="14,6"/>
<Setter Property="Margin" Value="4"/>
<Style.Triggers>
<!-- TRIGGER: ha az egér a gomb fölött van, a háttér változik -->
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{StaticResource KiemeltSzin}"/>
</Trigger>
</Style.Triggers>
</Style>

<!-- NEVESÍTETT stílus: csak ahol hivatkozol rá -->
<Style x:Key="Cim" TargetType="TextBlock">
<Setter Property="FontSize" Value="24"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Foreground" Value="{StaticResource FoSzin}"/>
</Style>
</Application.Resources>
</Application>

<!-- használat bármelyik ablakban -->
<TextBlock Text="Cím" Style="{StaticResource Cim}"/>
<Button Content="OK"/> <!-- automatikusan megkapja az implicit gomb-stílust -->
ErőforrásAz erőforrás (x:Key névvel) egy újrahasználható érték: szín, ecset, stílus, sablon. Az ablak (Window.Resources) vagy az egész program (Application.Resources, App.xaml) szintjén definiálhatod, és {StaticResource Kulcs} formában használod. Egy helyen módosítod, és mindenütt változik.
Stílus (Style)A stílus tulajdonság-értékek (Setter) gyűjteménye egy típusra (TargetType). Az implicit stílus (nincs x:Key) az adott típus minden elemére vonatkozik; a nevesített csak ahol Style="{StaticResource Cim}". Ez a WPF legnagyobb előnye a Windows Formshoz képest: egy helyen irányítod az egész program kinézetét.
TriggerA Trigger feltételhez kötött tulajdonságváltás kód nélkül: IsMouseOver, IsEnabled, IsFocused. Így készül a gomb hover-hatása a code-behind nélkül. Összetettebb esetre az EventTrigger és a DataTrigger (a 15.3 leckében) való.
Sablon (ControlTemplate)A stílus az értékeket állítja; a sablon a vezérlő szerkezetét definiálja újra (például egy kerek gomb): haladó téma, de a mechanizmus a lényege a WPF testreszabhatóságának.

Jósolj!

Az App.xamlban van egy implicit Button stílus (lila háttér). Az egyik ablakban egy gombot szeretnél, amely kivétel: piros. Mit teszel?

Jóslat ellenőrzése

A gombon közvetlenül megadott tulajdonság (Background="Red") felülírja a stílus értékét (a helyi érték erősebb). Több ilyen gombnál készíts nevesített stílust (x:Key="VeszelyesGomb"), és hivatkozz rá.

📷 Képernyőkép helye

Mit tegyél ide: a regisztrációs űrlap XAML-szerkesztője és a Designer nézet, a stílusozott gombokkal.Javasolt fájlnév: winforms-15-2-xaml.webp · Alt szöveg: Az XAML űrlap a Visual Studióban

Hibakeresés: te vagy a hibadetektív

Mi a baj, és hogyan javítod?

Gondold végig az okot, és csak utána nyisd le a megoldást.

1. XML-hiba a XAML-ben

<TextBlock Text="Tom & Jerry"/>
Hiba és javítás

A & jel XML-ben speciális. Text="Tom & Jerry". Ugyanígy a < → <.

2. Mindkét elem a Grid ugyanazon cellájában

Két vezérlő egymásra kerül.

Ok és javítás

Hiányzik a Grid.Row/Grid.Column (alap: 0, 0), vagy nincs RowDefinition. Add meg a cellát, vagy használj StackPanel-t.

3. A mező nem szélesedik az ablakkal

<TextBox Width="200"/>
Hiba és javítás

A fix Width megakadályozza a méretezést. Töröld, és hagyd a Stretch igazítást; ha kell korlát: MinWidth/MaxWidth.

4. A kezelő nem található

<Button Click="Mentes_Click"/>   <!-- CS1061: nincs ilyen metódus -->
Hiba és javítás

A code-behindban nincs Mentes_Click(object, RoutedEventArgs) metódus (vagy elírás van a névben). Add meg, vagy kattints duplán a gombra a Designerben.

5. A stílus nem érvényesül

A Style definiálva van, a gomb mégis alapkinézetű.

Ok és javítás

A TargetType nem egyezik (TargetType="TextBlock" gombra), nevesített stílusra nincs Style="{StaticResource ...}", vagy a gombon helyi érték felülírja. A stílus a használat előtt definiálva legyen (StaticResource).

6. A gomb szövege üres

A Text="Mentés" hibát vagy üres gombot ad.

Ok és javítás

A Button tulajdonsága Content, nem Text. Content="Mentés".

Mini projekt: névjegykártya-űrlap WPF-ben

Készíts egy névjegykártya-szerkesztő ablakot, amelynek minden eleme jól méreteződik, és a kinézete egy helyen irányítható:

  1. Projekt: új WPF Application (Nevjegykartya).
  2. Ablakszerkezet: DockPanel: felül Menu (Fájl → Új, Kilépés), alul StatusBar (üzenet), középen a tartalom.
  3. Szerkesztő rész (bal oldal): Grid űrlap (Auto és * oszlop): Név, Beosztás, E-mail, Telefon, Szín (ComboBox), Nagy betű (CheckBox), Betűméret (Slider).
  4. Előnézet (jobb oldal): egy Border (lekerekített sarok, CornerRadius) StackPanel-lel: a név, a beosztás, az elérhetőségek TextBlockban; a Frissít gomb (vagy TextChanged esemény) a mezők tartalmát az előnézetbe írja.
  5. Címkék: egy WrapPanel néhány címkével (diák, programozó, zene...), amely átméretezéskor tördelődik.
  6. Erőforrások és stílusok: az App.xamlban színek (SolidColorBrush), implicit Button stílus hover triggerrel, nevesített Cim stílus a TextBlockra.
  7. Méretezés-próba: az ablakot kicsinyítsd és nagyítsd; ellenőrizd, hogy a mezők kitöltik a szélességet, a WrapPanel tördel, semmi nem csúszik egymásra; MinWidth/MinHeight az ablakon.
  8. Kód: a code-behind csak a Frissit_Click és a Kilepes_Click kezelőt tartalmazza (az IsChecked == true helyes használata); a számítás/ellenőrzés külön osztályban.
  9. Naplo: az összehasonlítás: mi volt egyszerűbb, mint Windows Formsban (méretezés, stílus), és mi nehezebb (szintaxis, tanulás)? Írj 5–6 mondatot.
Megoldás megnyitása (próbáld ki előbb önállóan!)
App.xaml (részlet) és MainWindow.xaml + code-behindXAML / C#
<!-- App.xaml: Application.Resources -->
<SolidColorBrush x:Key="FoSzin" Color="#6840A5"/>
<SolidColorBrush x:Key="KiemeltSzin" Color="#8B60BA"/>
<Style TargetType="Button">
<Setter Property="Background" Value="{StaticResource FoSzin}"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="Padding" Value="14,6"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True"><Setter Property="Background" Value="{StaticResource KiemeltSzin}"/></Trigger>
</Style.Triggers>
</Style>
<Style x:Key="Cim" TargetType="TextBlock">
<Setter Property="FontSize" Value="22"/><Setter Property="FontWeight" Value="Bold"/><Setter Property="Foreground" Value="{StaticResource FoSzin}"/>
</Style>

<!-- MainWindow.xaml -->
<Window x:Class="Nevjegykartya.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Névjegykártya" Height="420" Width="720" MinWidth="560" MinHeight="360">
<DockPanel>
<Menu DockPanel.Dock="Top">
<MenuItem Header="_Fájl">
<MenuItem Header="_Kilépés" Click="Kilepes_Click"/>
</MenuItem>
</Menu>
<StatusBar DockPanel.Dock="Bottom"><TextBlock x:Name="lblAllapot" Text="Kész."/></StatusBar>

<Grid Margin="16">
<Grid.ColumnDefinitions><ColumnDefinition Width="*"/><ColumnDefinition Width="*"/></Grid.ColumnDefinitions>

<Grid Grid.Column="0" Margin="0,0,12,0">
<Grid.ColumnDefinitions><ColumnDefinition Width="Auto"/><ColumnDefinition Width="*"/></Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/><RowDefinition Height="Auto"/><RowDefinition Height="Auto"/><RowDefinition Height="Auto"/><RowDefinition Height="Auto"/><RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="Név:" Margin="0,0,8,8" VerticalAlignment="Center"/><TextBox x:Name="txtNev" Grid.Row="0" Grid.Column="1" Margin="0,0,0,8"/>
<TextBlock Grid.Row="1" Text="Beosztás:" Margin="0,0,8,8" VerticalAlignment="Center"/><TextBox x:Name="txtBeosztas" Grid.Row="1" Grid.Column="1" Margin="0,0,0,8"/>
<TextBlock Grid.Row="2" Text="E-mail:" Margin="0,0,8,8" VerticalAlignment="Center"/><TextBox x:Name="txtEmail" Grid.Row="2" Grid.Column="1" Margin="0,0,0,8"/>
<CheckBox x:Name="chkNagy" Grid.Row="3" Grid.Column="1" Content="Nagybetűs név" Margin="0,0,0,8"/>
<Slider x:Name="sldMeret" Grid.Row="4" Grid.Column="1" Minimum="14" Maximum="32" Value="22" Margin="0,0,0,8"/>
<Button Grid.Row="5" Grid.Column="1" Content="Frissítés" HorizontalAlignment="Right" VerticalAlignment="Top" Click="Frissit_Click" IsDefault="True"/>
</Grid>

<Border Grid.Column="1" BorderBrush="{StaticResource FoSzin}" BorderThickness="2" CornerRadius="10" Padding="16">
<DockPanel>
<WrapPanel DockPanel.Dock="Bottom" Margin="0,12,0,0">
<Border Background="#EEE4F7" CornerRadius="8" Padding="8,2" Margin="0,0,6,6"><TextBlock Text="diák"/></Border>
<Border Background="#EEE4F7" CornerRadius="8" Padding="8,2" Margin="0,0,6,6"><TextBlock Text="programozó"/></Border>
<Border Background="#EEE4F7" CornerRadius="8" Padding="8,2" Margin="0,0,6,6"><TextBlock Text="zene"/></Border>
</WrapPanel>
<StackPanel>
<TextBlock x:Name="lblNev" Style="{StaticResource Cim}" Text="Név" TextWrapping="Wrap"/>
<TextBlock x:Name="lblBeosztas" Text="Beosztás" Margin="0,4,0,12"/>
<TextBlock x:Name="lblEmail" Text="e-mail"/>
</StackPanel>
</DockPanel>
</Border>
</Grid>
</DockPanel>
</Window>

// ---- MainWindow.xaml.cs ----
private void Frissit_Click(object sender, RoutedEventArgs e)
{
string nev = txtNev.Text.Trim();

lblNev.Text = chkNagy.IsChecked == true ? nev.ToUpper() : nev; // bool? összehasonlítása
lblNev.FontSize = sldMeret.Value;
lblBeosztas.Text = txtBeosztas.Text;
lblEmail.Text = txtEmail.Text;
lblAllapot.Text = "Előnézet frissítve: " + DateTime.Now.ToString("HH:mm:ss");
}

private void Kilepes_Click(object sender, RoutedEventArgs e) { Close(); }

Megjegyzés: a fenti kódban a Style="{StaticResource Cim}" a Cim stílust az App.xamlból veszi; az App.xaml Application.Resources blokkjába tedd a stílus-részletet. A Close() az ablakot zárja (a program kilép, ha ez az utolsó ablak). A kinézet és a méretek verziófüggően kissé eltérhetnek; a saját képernyődön ellenőrizd.

📷 Képernyőkép helye

Mit tegyél ide: a kész névjegykártya-szerkesztő két méretben (kicsi és nagy ablak).Javasolt fájlnév: winforms-15-2-kesz.webp · Alt szöveg: A kész névjegykártya-szerkesztő

Három önálló gyakorlófeladat

Egyszerre csak egyet csinálj: tervezd meg, írd meg, futtasd, ellenőrizd, és csak utána nyisd ki a megoldást.

1. Panelválasztás

Rajzold le egy chat-ablak szerkezetét: fent a cím, lent a beviteli sor és a küldés gomb, középen az üzenetek. Milyen panelekkel építed fel?

Egy lehetséges megoldás

Egy DockPanel: Dock="Top" a cím, Dock="Bottom" egy Grid (két oszlop: * a beviteli mező, Auto a gomb), az utolsó elem a ScrollViewer az üzenetek StackPanel-jével. Nincs fix magasság.

2. Stílus-csere

Készíts két színtémát (világos és sötét) ResourceDictionary fájlként, és váltsd őket gombnyomásra.

Egy lehetséges megoldás

Két .xaml szótár ugyanazokkal a kulcsokkal (FoSzin, HatterSzin); az Application.Current.Resources.MergedDictionaries tartalmát cseréled (Clear, majd új ResourceDictionary { Source = new Uri(...) }); a DynamicResource hivatkozás frissül váltáskor (a StaticResource nem).

3. Kódból XAML

Írd át a leckebeli űrlapot úgy, hogy a mezőket ciklusban, C# kódból hozod létre egy Grid-be.

Egy lehetséges megoldás

Egy string[] címkékhez; minden elemhez RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto }), majd Grid.SetRow(elem, i), Grid.SetColumn(elem, 1). A tanulság: a XAML és a kód ugyanazt az objektumfát építi; a XAML olvashatóbb a rögzített felületre.

Gyakorlótár: 6 további feladat

Három szinten gyakorolhatsz: alap, közepes és kihívás. Csak a próbálkozás után nyisd le a megoldást.

Alap szint

1. XAML elem

Mi az <Button Content="OK"/> C# megfelelője?

Megoldás megnyitása

new Button { Content = "OK" }.

2. x:Name

Mire jó az x:Name?

Megoldás megnyitása

Nevet ad az elemnek, amelyen a code-behindban elérhető (mint a Windows Forms Name tulajdonsága).

Közepes szint

3. Margin

Mit jelent a Margin="0,0,8,8"?

Megoldás megnyitása

Bal 0, fent 0, jobb 8, lent 8 egység külső távolság.

4. Grid méretek

Mi a különbség az Auto és a * között?

Megoldás megnyitása

Az Auto a tartalom méretét veszi fel; a * a maradék helyet osztja el arányosan.

Kihívás szint

5. Implicit és nevesített

Mikor melyik stílust használod?

Megoldás megnyitása

Implicit (nincs x:Key): minden adott típusú elemre; nevesített: csak ahol hivatkozol rá (kiemelt gomb, cím).

6. Collapsed vagy Hidden

Melyik foglal helyet?

Megoldás megnyitása

A Hidden láthatatlan, de helyet foglal; a Collapsed láthatatlan és nem foglal helyet.

Gyors önellenőrzés

Válaszolj fejben, és csak utána nyisd le a választ.

1. Mi a XAML?

XML alapú nyelv, amely C# objektumokat hoz létre: a WPF felület leírása.

2. Hány gyereke lehet a Window-nak?

Egy (általában egy panel, amely a többit tartalmazza).

3. Melyik panel melyiknek jó?

StackPanel: lista; Grid: űrlap; DockPanel: menü és állapotsor; WrapPanel: tördelő sor.

4. Mit ad a Margin és a Padding?

A Margin külső, a Padding belső távolságot.

5. Mi az erőforrás?

Névvel (x:Key) ellátott újrahasználható érték: szín, stílus, sablon.

6. Mi a trigger?

Feltételhez kötött tulajdonságváltás (például IsMouseOver), kód nélkül.

7. Hogyan olvasod a CheckBox állapotát?

chk.IsChecked == true (az érték bool?).

Mit tudsz már?

  • Olvasod és írod a XAML-t, és érted, hogy az elemek objektumok.
  • Elrendezés-paneleket használsz (Grid, StackPanel, DockPanel, WrapPanel), és helyesen méreteződő ablakokat építesz.
  • Ismered a gyakori vezérlőket és a tartalom-modellt.
  • Erőforrásokat, stílusokat és triggereket használsz az egységes kinézetért.

Következő lecke: Adatkötés és MVVM fogalma

A felület és az adat összekötése: {Binding}, INotifyPropertyChanged, ViewModel és parancsok.