Składnia XAML i TextBlock
XAML wygląda jak HTML, ale rządzi się ściślejszymi zasadami: rozróżnia wielkość liter, każdy znacznik musi być zamknięty, a każdy znacznik tworzy prawdziwy obiekt C#. Poznasz te zasady na przykładzie napisu TextBlock, nauczysz się formatować fragmenty tekstu i zapisywać właściwości, które nie mieszczą się w zwykłym atrybucie.
Czego się dziś nauczysz
- Wyjaśnisz, że znacznik XAML tworzy obiekt, a atrybut ustawia jego właściwość, i zapiszesz ten sam napis w XAML i w C#.
- Zastosujesz zasady zapisu XAML: wielkość liter, zamykanie znaczników, cudzysłowy.
- Zapiszesz poprawnie liczby, kolory i wartości wyliczeniowe, także ułamki i znaki specjalne.
- Sformatujesz napis właściwościami czcionki, koloru, zawijania i wyrównania.
- Złożysz jeden napis z fragmentów o różnym wyglądzie (
Run,Bold,Italic,LineBreak). - Zapiszesz właściwość jako element, gdy wartość jest obiektem — na przykładzie tła z gradientem.
Znacznik to obiekt, atrybut to właściwość
XAML (eXtensible Application Markup Language) to krótszy zapis tworzenia obiektów. Każdy znacznik tworzy obiekt klasy o tej samej nazwie, każdy atrybut ustawia jedną właściwość. Te dwa zapisy robią dokładnie to samo:
<TextBlock Text="Witaj" FontSize="20" Foreground="DarkBlue"/>
TextBlock napis = new TextBlock(); // <TextBlock
napis.Text = "Witaj"; // Text="Witaj"
napis.FontSize = 20; // FontSize="20"
napis.Foreground = Brushes.DarkBlue; // Foreground="DarkBlue"/>
Content = napis; // włożenie napisu do okna
Zasada „znacznik = new, atrybut = przypisanie” tłumaczy każdy błąd w XAML: jeśli klasa nie ma danej właściwości w C#, to atrybut o tej nazwie też nie zadziała. W kursie wygląd okna opisujemy w XAML, bo od razu widać w nim strukturę. Kolory w C# (Brushes) dokładnie poznasz w lekcji 06 — tu wystarczy, że widzisz odpowiednik.
Zasady zapisu
| Zasada | Przykład |
|---|---|
| wielkość liter ma znaczenie | <TextBlock> ✓ <textblock> ✗ FontSize ✓ fontsize ✗ |
| każdy znacznik jest zamknięty | <TextBlock> … </TextBlock> albo samozamykający <TextBlock … /> |
| znaczniki zamykamy w odwrotnej kolejności | jak nawiasy: otwarty później — zamknięty wcześniej |
| wartość atrybutu zawsze w cudzysłowie | FontSize="20" ✓ FontSize=20 ✗ |
| atrybut tylko raz w znaczniku | <TextBlock Text="A" Text="B"/> ✗ |
| kolejność atrybutów nie ma znaczenia | Text="A" FontSize="20" = FontSize="20" Text="A" |
| komentarz | <!-- tekst --> — nie może stać w środku znacznika, między atrybutami |
Jak XAML czyta wartości
Każdy atrybut to tekst, ale właściwości mają różne typy. XAML zamienia tekst na właściwy typ:
| Typ właściwości | Zapis w XAML | Uwagi |
|---|---|---|
| liczba | FontSize="20", Opacity="0.5" | ułamki zawsze z kropką, niezależnie od ustawień Windows; Opacity to nieprzezroczystość od 0 (niewidoczny) do 1 (pełny) |
| logiczna | Topmost="True" | True / False |
| kolor | Foreground="DarkRed", "#8B0000" | nazwa albo zapis szesnastkowy |
| wyliczenie | FontWeight="Bold", TextAlignment="Center" | jedna z nazw podpowiadanych przez edytor |
| tekst | Text="Ala ma kota" | znaki specjalne — patrz niżej |
Znaki <, >, & i " mają w XAML znaczenie specjalne. W tekście zapisz je jako encje: <, >, &, ". Przykład: Text="Ben & Jerry" wyświetli „Ben & Jerry”. Nową linię w atrybucie zapiszesz encją .
Właściwości TextBlock
| Właściwość | Przykładowe wartości | Co robi |
|---|---|---|
FontSize | 12 (domyślnie), 20 | rozmiar czcionki |
FontWeight | Normal, SemiBold, Bold | grubość |
FontStyle | Normal, Italic | kursywa |
FontFamily | Segoe UI, Consolas, Georgia | krój pisma |
Foreground, Background | DarkRed, LightYellow | kolor tekstu i tła napisu |
TextWrapping | NoWrap (domyślnie), Wrap | zawijanie długiego tekstu |
TextAlignment | Left, Center, Right, Justify | wyrównanie linii tekstu |
TextDecorations | Underline, Strikethrough | podkreślenie, przekreślenie |
LineHeight | 28 | odstęp między liniami |
Czcionka w całym oknie
FontSize i FontFamily możesz też ustawić na Window — wtedy obowiązują dla wszystkich napisów, które nie mają własnej wartości. To tzw. dziedziczenie wartości; dokładniej w lekcji 05.
Fragmenty tekstu w jednym napisie
Atrybut Text daje jeden wygląd dla całego napisu. Gdy część tekstu ma być pogrubiona albo w innym kolorze, zamiast atrybutu wpisz zawartość między znacznikami <TextBlock> i </TextBlock>:
<TextBlock FontSize="16" TextWrapping="Wrap">
Sprawdzian z <Bold>matematyki</Bold> odbędzie się
<Run Text="w piątek" Foreground="Red" FontWeight="Bold"/>.
<LineBreak/>
<Italic>Przynieś kalkulator.</Italic>
</TextBlock>
Przynieś kalkulator.
jeden TextBlock, cztery różne fragmenty
| Element | Co robi |
|---|---|
<Run Text="…"/> | Fragment tekstu z własnymi właściwościami: Foreground, FontSize, FontWeight… Może mieć x:Name i zmieniać się z kodu. |
<Bold>…</Bold> | Pogrubiony fragment. |
<Italic>…</Italic> | Kursywa. |
<Underline>…</Underline> | Podkreślenie. |
<LineBreak/> | Przejście do nowej linii. |
Enter w XAML to spacja
Przejście do nowej linii w kodzie XAML między fragmentami zamienia się w jedną spację — nie w nową linię na ekranie. Nową linię robi tylko <LineBreak/>. Dlatego <Run Text="Stan na:"/> zapisany w jednej linii, a <Run x:Name="Data"/> w następnej dadzą razem „Stan na: 08.10.2026” — ze spacją, której nikt nie wpisał.
Właściwość zapisana jako element
Atrybut przyjmuje tylko tekst. Gdy wartość jest złożonym obiektem — np. tłem, którego kolor płynnie się zmienia — zapisujesz właściwość jako element w postaci <Klasa.Właściwość>:
<Window …>
<Window.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Color="LightYellow" Offset="0"/>
<GradientStop Color="Orange" Offset="1"/>
</LinearGradientBrush>
</Window.Background>
<TextBlock Text="Ogłoszenie"/>
</Window>
Kropka w nazwie znacznika oznacza: „to nie jest nowy obiekt, tylko właściwość Background obiektu Window”. LinearGradientBrush to tło z przejściem kolorów: StartPoint i EndPoint wyznaczają kierunek (0,0 — lewy górny róg, 0,1 — lewy dolny, czyli z góry na dół), a każdy GradientStop to kolor w miejscu Offset od 0 do 1.
Zapis jako atrybut Background="Orange" i jako element to dwa sposoby ustawienia tej samej właściwości. Nie wolno użyć obu naraz.
Okno ma jedną zawartość
<Window.Background> nie jest zawartością okna, tylko jego właściwością — dlatego obok niego może stać jeszcze jeden element (tu: TextBlock). Dwóch napisów bezpośrednio w oknie nadal nie zmieścisz.
Ogłoszenie kółka programistycznego
Całe ogłoszenie to jeden TextBlock złożony z fragmentów o różnym wyglądzie. Tło okna to gradient od jasnożółtego do pomarańczowego, a data „stan na” ustawia się sama przy uruchomieniu.
Nauczymy Cię pisać aplikacje okienkowe
Każdy czwartek, sala 21, godz. 14:30
Zapisy u wychowawcy
Stan na: 08.10.2026
okno po uruchomieniu
<Window x:Class="Lekcja02.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Ogłoszenie" Height="360" Width="460"
WindowStartupLocation="CenterScreen">
<!-- Właściwość zapisana jako element: tło z gradientem -->
<Window.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Color="LightYellow" Offset="0"/>
<GradientStop Color="Orange" Offset="1"/>
</LinearGradientBrush>
</Window.Background>
<!-- Jeden TextBlock, a w nim fragmenty o różnym wyglądzie -->
<TextBlock TextAlignment="Center" TextWrapping="Wrap"
HorizontalAlignment="Center" VerticalAlignment="Center"
FontSize="16">
<Run Text="KÓŁKO PROGRAMISTYCZNE" FontSize="26" FontWeight="Bold" Foreground="DarkRed"/>
<LineBreak/>
<Italic>Nauczymy Cię pisać aplikacje okienkowe</Italic>
<LineBreak/>
<LineBreak/>
<Run Text="Każdy czwartek, sala 21, godz. 14:30"/>
<LineBreak/>
<Bold>Zapisy u wychowawcy</Bold>
<LineBreak/>
<LineBreak/>
<Run Text="Stan na:" Foreground="Gray"/>
<Run x:Name="Data" Foreground="Gray"/>
</TextBlock>
</Window>
using System.Windows;
namespace Lekcja02;
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
// Run też może mieć nazwę i zmieniać się z kodu
Data.Text = DateTime.Now.ToString("dd.MM.yyyy");
}
}
Co dzieje się po kolei
<Window.Background>ustawia tło okna. Gradient biegnie z góry (0,0) na dół (0,1): na górze jasnożółty, na dole pomarańczowy.- Jedyną zawartością okna jest
TextBlock. Jego wspólne ustawienia — wyśrodkowanie, zawijanie, rozmiar 16 — dotyczą wszystkich fragmentów, chyba że fragment ma własne. - Pierwszy
Runma własnyFontSize="26", kolor i pogrubienie — dlatego tytuł jest większy od reszty. - Każdy
<LineBreak/>to nowa linia. Dwa pod rząd dają pustą linię odstępu. <Italic>i<Bold>zawierają zwykły tekst między znacznikami — nie potrzebująRun.- Ostatni
Runma nazwęData. Konstruktor wpisuje do niego dzisiejszą datę metodąToString("dd.MM.yyyy"). - Między „Stan na:” a datą widać spację, choć nie ma jej w żadnym
Text— to przejście do nowej linii w kodzie XAML między dwomaRun.
Sprawdź trzy rzeczy
- Zmień
EndPoint="0,1"naEndPoint="1,0". Gradient pobiegnie od lewej do prawej. - Dopisz do znacznika
<TextBlock>atrybutText="Test". Dostaniesz błąd — tekst ustawiony jest teraz dwa razy: atrybutem i zawartością. - Zapisz oba ostatnie
Runw jednej linii, bez spacji między nimi:…Foreground="Gray"/><Run x:Name=…. Spacja przed datą zniknie.
Zestawienie elementów
| Element | Znaczenie | Uwagi |
|---|---|---|
TextBlock | napis | Tekst w Text albo jako zawartość z fragmentami. |
FontSize, FontWeight, FontStyle, FontFamily | czcionka | Mogą być ustawione też na fragmencie lub na oknie. |
TextWrapping, TextAlignment | zawijanie i wyrównanie linii | Długi tekst bez Wrap wychodzi poza okno. |
TextDecorations | podkreślenie, przekreślenie | Underline, Strikethrough. |
Run | fragment tekstu | Ma własne właściwości i może mieć x:Name. |
Bold, Italic, Underline | fragment z formatowaniem | Tekst wpisujesz między znacznikami. |
LineBreak | nowa linia | Enter w kodzie XAML to tylko spacja. |
<Window.Background> | właściwość jako element | Dla wartości, które nie mieszczą się w atrybucie. |
LinearGradientBrush, GradientStop | tło z przejściem kolorów | Kierunek: StartPoint/EndPoint; kolory: Color i Offset 0–1. |
<, &, | encje | Znaki specjalne i nowa linia w atrybucie. |
ToString("dd.MM.yyyy") | data jako tekst | Format daty dla DateTime. |
Zanim utkniesz
| Zapis | Problem |
|---|---|
<TextBlock Text="A">B</TextBlock> | Tekst ustawiony dwa razy — atrybutem i zawartością. Wybierz jeden sposób. |
Opacity="0,5" | W XAML ułamki zawsze z kropką: 0.5. |
FontSize=20 | Brak cudzysłowu — atrybut nie zostanie przyjęty. |
Text="x < 10" | Znak < w tekście trzeba zapisać jako <. |
<Bold> otwarty, a zamknięty </TextBlock> | Znaczniki zamykamy w odwrotnej kolejności niż otwieramy. |
Background="Orange" i <Window.Background> naraz | Ta sama właściwość ustawiona dwa razy. |
<TextBlock.Background> wewnątrz <Window> | Przedrostek musi być nazwą klasy elementu, w którym stoisz: <Window.Background>. |
| Enter w XAML, żeby przejść do nowej linii | Na ekranie pojawi się tylko spacja. Użyj <LineBreak/>. |
Foreground="Ciemnoczerwony" | Nazwy kolorów są angielskie. Gdy nie znasz nazwy, wpisz # i kod szesnastkowy (lekcja 06). |
Zadania
Każde zadanie wykonaj w nowym projekcie Aplikacja WPF. Okno ma jedno miejsce na zawartość — w tej lekcji wszystko mieści się w jednym TextBlock. Wskazówkę otwórz dopiero wtedy, gdy utkniesz.
Zapisz w XAML napis, który ten kod tworzy w C#. Uruchom program i porównaj wygląd z opisem w komentarzach. W komentarzu XAML przy każdym atrybucie napisz, którą linię z C# zastępuje.
TextBlock baner = new TextBlock();
baner.Text = "Promocja: drugi zeszyt gratis!";
baner.FontSize = 28;
baner.FontWeight = FontWeights.Bold;
baner.FontStyle = FontStyles.Italic;
baner.Foreground = Brushes.Crimson;
baner.TextWrapping = TextWrapping.Wrap;
baner.TextAlignment = TextAlignment.Center;
baner.VerticalAlignment = VerticalAlignment.Center;
pokaż wskazówkę
- Przy wartościach wyliczeniowych w XAML zostaje tylko część po ostatniej kropce, np.
Bold. Brushes.Crimsonw XAML to sama nazwa koloru.
Zbuduj okno 360 × 200 z wizytówką: w pierwszej linii imię i nazwisko (rozmiar 22, pogrubione), w drugiej rola, np. „uczeń klasy 3 TP — technik programista” (kursywa, szara), po pustej linii adres e-mail (podkreślony, niebieski) i numer sali. Wszystko w jednym TextBlock, wyśrodkowane w oknie.
uczennica klasy 3 TP — technik programista
ola.nowak@szkola.pl · sala 21
przykładowy wygląd
pokaż wskazówkę
- Fragment z kilkoma własnymi ustawieniami (rozmiar, pogrubienie) najwygodniej zapisać jako
Run. - Pusta linia to dwa
LineBreakpod rząd.
Zrób plakat szkolnego koncertu w oknie 400 × 500. Tło okna to pionowy gradient z trzech kolorów: na górze MidnightBlue, w połowie MediumPurple, na dole Pink. Na środku biały, wyśrodkowany tekst: tytuł „KONCERT JESIENNY” (rozmiar 32, pogrubiony), data i godzina, miejsce oraz przekreślona stara cena „15 zł” obok nowej „wstęp wolny”. W komentarzu zapisz, co się stanie, jeśli środkowy kolor dostanie Offset="0.2" — a potem sprawdź to.
pokaż wskazówkę
- Gradient pionowy: zmienia się druga liczba punktów
StartPointiEndPoint. Trzy kolory to trzyGradientStop. - Przekreślenie fragmentu:
TextDecorations="Strikethrough"naRun. - Biały kolor dla całego tekstu ustaw raz, na
TextBlock.
Okno pokazuje „Cytat dnia” — inny w każdy dzień tygodnia. W kodzie przygotuj tablicę 7 krótkich cytatów i tablicę 7 autorów. Napis składa się z nagłówka „Cytat na poniedziałek:” (pogrubiony, nazwa dnia dobiera się sama), pustej linii, cytatu w kursywie i autora wyrównanego w tej samej linii po myślniku. Nagłówek, cytat i autor to trzy nazwane fragmenty Run, które wypełnia konstruktor. W komentarzu wyjaśnij, jak zamieniasz dzień tygodnia na indeks tablicy.
pokaż wskazówkę
DateTime.Now.DayOfWeekto wartość wyliczeniowa; rzutowana naintdaje 0 dla niedzieli, 1 dla poniedziałku itd.- Polską nazwę dnia da
DateTime.Now.ToString("dddd").
Zrób okno-ściągawkę z operatorami C#, które zawierają znaki specjalne XAML. Każda linia: operator czcionką Consolas (pogrubiony) i jego opis zwykłą czcionką, np. „&& — i (oba warunki prawdziwe)”, „<= — mniejsze lub równe”, „=> — strzałka w wyrażeniach lambda”, „" — cudzysłów zaczyna tekst”. Co najmniej 6 operatorów. Jeżeli projekt się nie kompiluje, w komentarzu zapisz, który znak spowodował błąd i jak go zapisałeś.
pokaż wskazówkę
- Zajrzyj do tabeli encji w sekcji „Jak XAML czyta wartości”.
- Krój pisma fragmentu ustawisz atrybutem
FontFamilynaRun.
Poniższy plik ma sześć błędów. Przepisz go do projektu Plakat, popraw wszystkie i przy każdym zostaw komentarz z opisem. Gotowe okno ma mieć tło z gradientem od białego do jasnozielonego i wyśrodkowany, półprzezroczysty napis.
<Window x:Class="Plakat.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Plakat" Height=300 Width="400" Background="White">
<window.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Color="White" Offset="0"/>
<GradientStop Color="LightGreen" Offset="1"/>
</LinearGradientBrush>
</window.Background>
<TextBlock Text="Dzień Ziemi" FontSize="30" Opacity="0,8"
HorizontalAlignment="Center" VerticalAlignment="Center">
<Bold>22 kwietnia & cała szkoła</Bold>
</TextBlock>
</Window>
pokaż wskazówkę
- Sprawdź po kolei: cudzysłowy, wielkość liter w nazwie znacznika, właściwość ustawioną dwa razy (są takie dwie sytuacje), zapis ułamka i znak specjalny w tekście.
- Gdy w napisie ma zostać i nazwa święta, i data, połącz je w jednej zawartości z
LineBreak.
Co trzeba zapamiętać
- Znacznik XAML tworzy obiekt, atrybut ustawia jego właściwość — wszystko z XAML da się zrobić w C#.
- XAML rozróżnia wielkość liter, wymaga zamykania znaczników i cudzysłowów.
- Ułamki w XAML zawsze z kropką; znaki
< > & "zapisuj encjami. - Napis z fragmentami: zawartość
TextBlockzRun,Bold,Italic,LineBreak. - Enter w kodzie XAML między fragmentami to spacja, nie nowa linia.
- Złożoną wartość zapisujesz jako element
<Klasa.Właściwość>, np. gradient w<Window.Background>.
Dokumentacja: Microsoft Learn — XAML w WPF, klasa TextBlock.