Projekt WPF i okno
Do tej pory programy działały w konsoli: wypisywały tekst i czekały na odpowiedź. Na egzaminie INF.04 część zadania to aplikacja z oknem. Zaczynamy od podstaw: tworzysz projekt, poznajesz jego pliki, ustawiasz okno i wyświetlasz w nim pierwszy napis — także z kodu C#.
Czego się dziś nauczysz
- Wyjaśnisz, czym program sterowany zdarzeniami różni się od programu konsolowego.
- Utworzysz projekt Aplikacja WPF dla .NET 10 i uruchomisz go.
- Opiszesz rolę plików
App.xaml,MainWindow.xamliMainWindow.xaml.cs. - Wyjaśnisz, co robi
InitializeComponent()i dlaczego kod zmieniający okno stoi po nim. - Ustawisz tytuł, rozmiar, tło i sposób zmiany rozmiaru okna.
- Wyświetlisz napis
TextBlocki zmienisz go z kodu przez nazwę zx:Name.
Konsola a okno — inny sposób myślenia
Program konsolowy sam prowadzi rozmowę: wypisuje pytanie, czeka na odpowiedź, liczy i kończy pracę. Program okienkowy wyświetla okno i czeka, aż użytkownik coś zrobi — kliknie, wpisze tekst — i dopiero wtedy reaguje. Takie działanie nazywamy programowaniem sterowanym zdarzeniami.
| Aplikacja konsolowa | Aplikacja WPF | |
|---|---|---|
| Kto decyduje o kolejności | program — instrukcja po instrukcji | użytkownik — działa w dowolnej kolejności |
| Wypisanie wyniku | Console.WriteLine() | napis w oknie (TextBlock) |
| Wczytanie danych | Console.ReadLine() | pole tekstowe (lekcja 07) |
| Koniec programu | po ostatniej instrukcji | gdy użytkownik zamknie okno |
WPF (Windows Presentation Foundation) to część platformy .NET do aplikacji okienkowych. Program WPF ma dwie warstwy: wygląd opisany w języku XAML (czytaj: „zamel”) oraz działanie zapisane w C#.
A Windows Forms?
W Visual Studio zobaczysz też szablon Windows Forms — starszą technologię okienkową. W tym kursie używamy wyłącznie WPF: wygląd opisujemy w XAML, a okna dobrze dopasowują się do rozmiaru i skalowania ekranu.
Tworzenie projektu krok po kroku
Potrzebujesz Visual Studio 2026 z pakietem roboczym Programowanie aplikacji klasycznych .NET. Jeśli go brakuje, doinstalujesz go w programie Visual Studio Installer przyciskiem Modyfikuj.
| Krok | Co robisz | Na co uważać |
|---|---|---|
| 1 | Na ekranie startowym wybierz Utwórz nowy projekt. | Z menu: Plik → Nowy → Projekt. |
| 2 | Wyszukaj WPF i wybierz Aplikacja WPF z oznaczeniem C#. | Nie wybieraj Aplikacja WPF (.NET Framework) — to stara platforma. |
| 3 | Wpisz nazwę, np. Lekcja01, i wybierz folder. | Bez spacji i polskich znaków — z nazwy powstaje przestrzeń nazw w kodzie. |
| 4 | W polu Struktura wybierz .NET 10.0. | Wszystkie przykłady kursu są dla .NET 10. |
| 5 | Kliknij Utwórz i uruchom program klawiszem F5. | Pojawi się puste okno „MainWindow”. Zamknij je, żeby wrócić do edycji. |
| Okno Visual Studio | Do czego służy |
|---|---|
| Eksplorator rozwiązań | Lista plików projektu. Dwuklik otwiera plik. |
Projektant (górna część pliku .xaml) | Podgląd okna na żywo. |
Edytor XAML (dolna część pliku .xaml) | Tu piszesz wygląd okna. W kursie piszemy XAML ręcznie — tak jest dokładniej niż przeciąganiem z Przybornika. |
| Właściwości | Właściwości zaznaczonego elementu. |
F5 czy Ctrl + F5?
F5 uruchamia program z debugerem (można go zatrzymywać i podglądać zmienne), Ctrl + F5 — bez debugera, trochę szybciej. Część zmian w XAML widać od razu w działającym programie, ale zmiany w C# sprawdzaj po ponownym uruchomieniu.
Pliki nowego projektu
├── Lekcja01.csprojustawienia projektu: .NET 10, WPF
├── App.xamlaplikacja: które okno otworzyć na starcie
├── App.xaml.cskod aplikacji (na razie pusty)
├── AssemblyInfo.csinformacje techniczne — nie zmieniamy
├── MainWindow.xamlWYGLĄD głównego okna
└── MainWindow.xaml.csDZIAŁANIE głównego okna (code-behind)
Prawie całą pracę wykonujesz w dwóch ostatnich plikach. Tak wyglądają zaraz po utworzeniu projektu (szablon dodaje kilka dodatkowych linii, które na razie pomijamy):
<Window x:Class="Lekcja01.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="450" Width="800">
<Grid>
</Grid>
</Window>
using System.Windows;
namespace Lekcja01;
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
| Fragment | Co znaczy |
|---|---|
x:Class="Lekcja01.MainWindow" | Ten XAML opisuje klasę MainWindow z przestrzeni nazw Lekcja01. Musi się zgadzać z klasą w pliku .cs. |
xmlns="…", xmlns:x="…" | Przestrzenie nazw XAML — skąd pochodzą znaczniki. Nie zmieniamy ich. |
<Grid> … </Grid> | Pojemnik, który szablon wstawia do okna. Na razie traktuj go jako miejsce na jeden napis — jak dzielić go na wiersze i kolumny, nauczysz się w lekcji 09. |
public partial class MainWindow : Window | Klasa okna. partial znaczy, że klasa jest podzielona na kilka plików — drugą część Visual Studio tworzy samo z XAML. |
InitializeComponent(); | Wczytuje XAML i tworzy wszystko, co w nim opisano. Bez tej linii okno będzie puste. |
Skąd program wie, które okno otworzyć?
Z pliku App.xaml: atrybut StartupUri="MainWindow.xaml" wskazuje okno startowe.
Właściwości okna
Wygląd i zachowanie okna ustawiasz atrybutami znacznika <Window>. Po wpisaniu spacji w znaczniku Visual Studio podpowie listę właściwości, a po =" — dozwolone wartości.
| Właściwość | Przykład | Co robi |
|---|---|---|
Title | "Biblioteka" | Napis na pasku tytułu i na pasku zadań. |
Width, Height | 480, 300 | Rozmiar okna przy otwarciu. |
MinWidth, MinHeight | 380, 250 | Mniejszego okna użytkownik nie zrobi. |
WindowStartupLocation | CenterScreen, Manual | Gdzie okno się pojawi. Przy Manual położenie ustawiają Left i Top. |
Left, Top | 20, 20 | Odległość okna od lewej i górnej krawędzi ekranu. |
ResizeMode | CanResize, CanMinimize, NoResize | Czy można zmieniać rozmiar. CanMinimize — tylko minimalizacja. |
Background | AliceBlue, #FFEFEFEF | Tło okna — nazwa koloru albo zapis szesnastkowy (szczegóły w lekcji 06). |
Topmost | True | Okno zawsze nad innymi oknami. |
Każdą z tych właściwości możesz też ustawić w C#. W klasie okna piszesz samą nazwę, bez niczego przed kropką — bo chodzi o to okno:
public MainWindow()
{
InitializeComponent();
Title = "Ustawione z kodu"; // to samo co Title="…" w XAML
Width = 600;
Topmost = true;
}
Pierwszy napis: TextBlock
TextBlock wyświetla tekst. Wstawiasz go do <Grid> z szablonu:
<Grid>
<TextBlock x:Name="Powitanie"
Text="Cześć!"
FontSize="24" FontWeight="Bold" Foreground="DarkBlue"
HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
| Właściwość | Co robi |
|---|---|
Text | Wyświetlany tekst. |
FontSize, FontWeight | Rozmiar czcionki (domyślnie 12) i grubość, np. Bold. |
Foreground | Kolor tekstu, np. DarkBlue. |
HorizontalAlignment, VerticalAlignment | Położenie napisu w oknie. Center — na środku. Bez nich napis stoi w lewym górnym rogu. Więcej w lekcji 05. |
TextWrapping="Wrap" | Długi tekst zawija się do nowej linii. |
TextAlignment="Center" | Wyśrodkowanie linii tekstu wewnątrz napisu. |
x:Name — nazwa do użycia w kodzie
Atrybut x:Name="Powitanie" tworzy w klasie okna pole o tej nazwie. Dzięki temu w C# napiszesz Powitanie.Text = "…";. Nazwę nadajesz tylko elementom, które zmieniasz w kodzie. W kursie nazwy zaczynamy wielką literą i piszemy po polsku bez ogonków.
Najpierw InitializeComponent(), potem reszta
Napis Powitanie powstaje dopiero w InitializeComponent(). Kod, który go zmienia, musi stać pod tą linią — wcześniej pole Powitanie jest puste (null) i program zakończy się błędem przy starcie.
Okno biblioteki szkolnej
Okno ma stały rozmiar, jasnoniebieskie tło i napis powitalny na środku. Konstruktor dopisuje do tytułu dzisiejszą datę i zmienia napis — tak, jakby program sprawdzał godziny otwarcia.
Dziś czynne do 15:30.
okno po uruchomieniu — tytuł i napis ustawił konstruktor
<Window x:Class="Lekcja01.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Biblioteka szkolna" Height="300" Width="480"
MinHeight="250" MinWidth="380"
WindowStartupLocation="CenterScreen"
ResizeMode="CanMinimize"
Background="AliceBlue">
<Grid>
<TextBlock x:Name="Powitanie"
Text="Witaj w bibliotece szkolnej!"
FontSize="24" FontWeight="Bold" Foreground="DarkBlue"
TextWrapping="Wrap" TextAlignment="Center"
HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</Window>
using System.Windows;
namespace Lekcja01;
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
// Po InitializeComponent okno i napis już istnieją — można je zmieniać z kodu
Title = $"Biblioteka szkolna — {DateTime.Now:dd.MM.yyyy}";
Powitanie.Text = $"Witaj w bibliotece szkolnej!\nDziś czynne do 15:30.";
}
}
Co dzieje się po kolei
App.xamlwskazujeMainWindow.xamljako okno startowe, więc program tworzy obiektMainWindowi wywołuje jego konstruktor.InitializeComponent()czyta XAML: ustawia tytuł „Biblioteka szkolna”, rozmiar 480 × 300, tło i tworzy napisPowitanie.- Dopiero teraz wykonują się dwie linie pod spodem. Pierwsza nadpisuje tytuł z XAML — dlatego na pasku widać datę.
{DateTime.Now:dd.MM.yyyy}wstawia dzisiejszą datę w formacie dzień.miesiąc.rok. - Druga linia zmienia tekst napisu. Znak
\nto nowa linia — napis ma dwa wiersze, aTextAlignment="Center"wyśrodkowuje oba. ResizeMode="CanMinimize"sprawia, że okna nie da się powiększyć ani przeciągnąć krawędzią — przycisk maksymalizacji zniknął.- Napis stoi na środku dzięki
HorizontalAlignmentiVerticalAlignmentustawionym naCenter.
Sprawdź trzy rzeczy
- Przenieś linię
Title = …nadInitializeComponent(). Na pasku znów zobaczysz „Biblioteka szkolna” — XAML wykonał się później i nadpisał tytuł z kodu. - Przenieś nad
InitializeComponent()linięPowitanie.Text = …. Program zakończy się przy starcie błędemNullReferenceException— napisu jeszcze nie było. - Usuń
HorizontalAlignmentiVerticalAlignment. Napis przeskoczy do lewego górnego rogu.
Zestawienie elementów
| Element | Znaczenie | Uwagi |
|---|---|---|
Window | okno programu | Może zawierać tylko jeden element w środku. |
Title, Width, Height | tytuł i rozmiar okna | W C# w klasie okna: Title = "…"; |
MinWidth, MinHeight | minimalny rozmiar | Chroni napisy przed ucięciem. |
WindowStartupLocation | miejsce otwarcia okna | CenterScreen albo Manual z Left/Top. |
ResizeMode | zmiana rozmiaru | CanResize (domyślnie), CanMinimize, NoResize. |
Background, Topmost | tło, okno zawsze na wierzchu | W C#: Topmost = true; |
TextBlock | napis | Tekst w Text. Dokładniej w lekcji 02. |
x:Name | nazwa elementu w kodzie | Tworzy pole w klasie okna. |
InitializeComponent() | tworzy okno z XAML | Kod zmieniający elementy — zawsze pod nią. |
DateTime.Now | bieżąca data i godzina | Format w interpolacji: {DateTime.Now:dd.MM.yyyy}, {DateTime.Now:HH:mm}. |
\n | nowa linia w napisie | Działa w Text ustawianym z C#. |
Zanim utkniesz
| Zapis lub sytuacja | Problem |
|---|---|
| szablon Aplikacja WPF (.NET Framework) | Projekt na starej platformie — inne pliki i ustawienia, część przykładów nie zadziała. Utwórz projekt jeszcze raz. |
dwa TextBlock bezpośrednio w <Window> | Błąd The property 'Content’ is set more than once. Okno ma jedno miejsce na zawartość — jak zmieścić więcej elementów, pokaże lekcja 03. |
title="…" zamiast Title="…" | XAML rozróżnia wielkość liter — właściwość title nie istnieje. |
kod zmieniający napis nad InitializeComponent() | NullReferenceException przy starcie — napis jeszcze nie istnieje. |
usunięte InitializeComponent(); | Okno uruchamia się puste. |
x:Class="Lekcja01.MainWindow", a w C# namespace Lekcja1; | CS0103: The name 'InitializeComponent’ does not exist — XAML i C# opisują różne klasy. Kopiując kod z kursu, zmień Lekcja01 na nazwę swojego projektu w obu plikach. |
Powitanie.text = "…"; | CS1061 — w C# też liczy się wielkość liter: właściwość to Text. |
| błąd MSB3027: The file is locked | Program nadal działa (okno schowane za innymi). Zamknij go i zbuduj ponownie. |
Zadania
Każde zadanie wykonaj w nowym projekcie Aplikacja WPF. Wskazówkę otwórz dopiero wtedy, gdy utkniesz.
Szkoła stawia w holu ekran z informacją o dyżurach. Zbuduj okno o tytule „Informacja — sekretariat”, rozmiarze 600 × 260, otwierane na środku ekranu, bez możliwości zmiany rozmiaru (minimalizacja ma działać), z tłem Honeydew. Na środku okna wyświetl zawijany, wyśrodkowany napis rozmiaru 22: „Sekretariat czynny od poniedziałku do piątku w godzinach 7:30–15:30”. Zmień szerokość okna w XAML na 350 i sprawdź, czy napis nadal się mieści — w komentarzu w XAML zapisz, która właściwość napisu o tym decyduje.
oczekiwany wygląd (pomniejszony)
pokaż wskazówkę
- Wszystko ustawisz w XAML — kod C# nie jest potrzebny.
- Zawijanie i wyśrodkowanie linii tekstu to dwie różne właściwości napisu.
Zbuduj okno „Dziennik”, w którym konstruktor ustawia tytuł w postaci „Dziennik — czwartek, 8 października 2026” (aktualny dzień tygodnia i data, po polsku), a napis na środku okna pokazuje bieżącą godzinę w formacie „Zalogowano o 12:05”. Uruchom program dwa razy w odstępie minuty i sprawdź, że godzina się zmienia. W komentarzu w kodzie napisz, dlaczego godzina w oknie nie zmienia się sama, gdy program jest otwarty.
pokaż wskazówkę
- Dzień tygodnia i miesiąc słownie da format
dddd, d MMMM yyyy, a godzinę —HH:mm. - Napis potrzebuje
x:Name, a przypisania muszą stać podInitializeComponent().
Okno „Ile jeszcze?” pokazuje dużym, pogrubionym napisem liczbę dni do najbliższych wakacji, np. „Do wakacji zostało 263 dni”. Datę początku wakacji zapisz w kodzie jako stałą (np. 27 czerwca 2027). Jeśli wakacje już trwają (liczba dni jest ujemna albo równa zero), napis ma brzmieć „Wakacje! Odpocznij od komputera.”. W tytule okna pokaż datę początku wakacji.
przykładowy wynik
pokaż wskazówkę
- Różnica dwóch dat (
DateTime) daje przedział czasu, który ma właściwośćDays. Porównuj daty bez godzin:DateTime.Today. - Wybór napisu to zwykłe
if / elsew konstruktorze.
Zbuduj małe okno „Pamiętaj!” o rozmiarze 260 × 140, które otwiera się w lewym górnym rogu ekranu (20 jednostek od krawędzi), jest zawsze nad innymi oknami, ma żółte tło i nie da się go zmniejszyć poniżej rozmiaru startowego. Napis: „Oddać projekt z programowania do piątku”. Sprawdź „zawsze na wierzchu”, klikając w inne okno. Następnie przenieś ustawienie Topmost z XAML do konstruktora i zapisz w komentarzu, czy coś się zmieniło.
pokaż wskazówkę
- Żeby okno otworzyło się w podanym miejscu,
WindowStartupLocationmusi mieć wartośćManual. - Minimalny rozmiar ustawiają dwie właściwości z przedrostkiem
Min.
Okno recepcji wita gościa w zależności od godziny uruchomienia: 5:00–11:59 „Dzień dobry!”, 12:00–17:59 „Miłego popołudnia!”, 18:00–21:59 „Dobry wieczór!”, w pozostałych godzinach „Dobranoc — recepcja nieczynna”. Tytuł okna zawiera godzinę, np. „Recepcja (12:05)”. Żeby przetestować wszystkie przypadki bez czekania, zapisz godzinę w zmiennej, którą na czas testów ustawisz ręcznie, a na koniec przywróć DateTime.Now.Hour. W komentarzu wypisz cztery godziny, którymi sprawdziłeś granice przedziałów.
pokaż wskazówkę
- Godzinę jako liczbę daje
DateTime.Now.Hour(0–23). - Najlepiej testować wartości na granicach: 5, 11, 12, 22 itd.
Kolega przysłał projekt Kantor, który się nie kompiluje. Utwórz projekt o tej nazwie, przepisz kod i znajdź wszystkie błędy (jest ich pięć). Przy każdym poprawionym miejscu dopisz komentarz z opisem błędu. Program ma pokazywać na środku okna napis „Kurs euro: 4,30 zł”, a w tytule — godzinę uruchomienia.
<Window x:Class="Kantor.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
title="Kantor" Height="250" Width="350">
<TextBlock x:Name="Kurs" Text="Kurs euro: 4,30 zł" FontSize="20"
HorizontalAlignment="Center" VerticalAlignment="Center"/>
<TextBlock Text="Zapraszamy"/>
</Window>
using System.Windows;
namespace Kantor;
public partial class MainWindow : Window
{
public MainWindow()
{
kurs.Text = "Kurs euro: 4,30 zł";
InitializeComponent()
Title = $"Kantor ({DateTime.Now:HH:mm})";
}
}
pokaż wskazówkę
- Dwa błędy są w XAML: wielkość liter jednego atrybutu i liczba elementów bezpośrednio w oknie.
- Trzy błędy są w C#: brakujący znak, nazwa niezgodna z
x:Namei kolejność linii w konstruktorze. - Poprawiaj po jednym błędzie i czytaj listę błędów od góry — jeden błąd składni potrafi wywołać kilka komunikatów.
Co trzeba zapamiętać
- Program okienkowy jest sterowany zdarzeniami — czeka na działanie użytkownika.
- Szablon: Aplikacja WPF (C#), struktura .NET 10.0 — nie wersja „.NET Framework”.
MainWindow.xaml— wygląd,MainWindow.xaml.cs— działanie. Razem tworzą jedną klasę (partial).InitializeComponent()tworzy elementy z XAML; kod, który je zmienia, stoi pod tą linią.- Okno ma jedno miejsce na zawartość.
Title,Width,Height,MinWidth,WindowStartupLocation,ResizeMode,Background,Topmost— podstawowe właściwości okna, dostępne też z C#.x:Namenadaje elementowi nazwę, przez którą zmienisz go w kodzie, np.Powitanie.Text = "…";.
Dokumentacja: Microsoft Learn — pierwsza aplikacja WPF, klasa Window.