C# WinForms и WPF — простые окна
Приветствую! Здесь вы наверняка найдете, что ищете. Примеры в лаборатории рассчитаны на то, что мы разбираем что-то конкретное.
Текущая статья посвящена примерам: WinForms и WPF на C# с построчным разбором.
Поэтому за теорией по текущей теме вам — в энциклопедию. Если ещё не погружались, то маршрут прост:
- Основы
- Система и сеть
- Данные и разметка
- Код и разработка
- Языки
- Искусственный интеллект
- Проект
- Инфраструктура и безопасность
- Спин-офф
Обязательно пройдитесь.
А теперь приступим к нашему предмету.
Обзор платформ — WinForms и WPF с нуля.
Рецепты по каждому элементу — справочник WinForms и справочник WPF.
Аналог на Python — Tkinter — окна и виджеты.
Синтаксис C# — первая программа.
Навигация по примерам
| Раздел | Тема |
|---|---|
| Каркас WinForms | winforms program.cs пример, application.run c#, statthread winforms |
| Каркас WPF | wpf mainwindow xaml пример, initializecomponent, startupuri |
| Окно с текстом | winforms label пример, wpf textblock, как сделать окно c# |
| Кнопка и MessageBox | winforms button click, messagebox.show c#, wpf button click event |
| Поле ввода и имя | winforms textbox get text, wpf textbox x:name, форма ввода c# |
| Конвертер °C → °F | конвертер температуры winforms, tryparse c# textbox, курсовая калькулятор c# |
| CheckBox и RadioButton | winforms checkbox, wpf radiobutton groupname, настройки форма c# |
| Список задач | winforms listbox add item, wpf listbox пример, todo list c# gui |
| Форма входа | winforms tablelayoutpanel, wpf grid passwordbox, форма логин c# |
| Меню | winforms menustrip, wpf menu menuitem, statusbar c# |
| OpenFileDialog | openfiledialog c#, microsoft.win32.openfiledialog wpf |
| Привязка WPF | wpf binding textbox, datacontext пример, binding mode |
| Частые ошибки | окно сразу закрывается winforms, net8.0-windows, invoke ui thread |
WinForms и WPF — что выбрать для учебного проекта
| WinForms | WPF | |
|---|---|---|
| Разметка | Код C# или визуальный Designer в Visual Studio | XAML + code-behind |
| Отрисовка | GDI+, «родные» окна Windows | DirectX, векторный UI |
| Привязка данных | Базовая | {Binding}, MVVM |
| Шаблон проекта | dotnet new winforms |
dotnet new wpf |
| Когда удобнее | Быстрая утилита, CRUD, legacy | Кастомный UI, стили, анимации |
Для первого окна подойдут оба стека. WinForms проще «увидеть результат в одном .cs файле»; WPF учит XAML — это пригодится в практикуме WPF.
Создание проекта
WinForms:
dotnet new winforms -n MyDesktopApp -o MyDesktopApp
cd MyDesktopApp
dotnet run
WPF:
dotnet new wpf -n MyWpfApp -o MyWpfApp
cd MyWpfApp
dotnet run
Разбор команд
| Команда | Смысл |
|---|---|
dotnet new winforms |
Шаблон с Program.cs, Form1.cs, флагом UseWindowsForms в .csproj |
dotnet new wpf |
Шаблон с App.xaml, MainWindow.xaml, флагом UseWPF |
-n MyDesktopApp |
Имя проекта и namespace по умолчанию |
-o MyDesktopApp |
Папка на диске |
dotnet run |
Сборка и запуск; откроется пустое окно |
Появится пустое окно — шаблон уже рабочий. Примеры ниже можно заменить содержимое Program.cs (WinForms) или MainWindow.xaml + MainWindow.xaml.cs (WPF).
Из чего состоит десктоп-приложение на C#
В консольной программе всё крутится вокруг Main() и Console.ReadLine(). В WinForms и WPF точка входа та же, но вместо текста в консоли — окно и цикл сообщений, который ждёт клики и ввод.
flowchart LR
A[Main / App.xaml] --> B[Создание окна Form или Window]
B --> C[Контролы Label Button TextBox]
C --> D[Application.Run или Show]
D --> E{Событие?}
E -->|Click KeyDown| F[Обработчик C#]
E -->|Закрытие| G[Выход]
F --> D
| Часть | WinForms | WPF | Роль |
|---|---|---|---|
| Точка входа | Program.Main() |
App.xaml → StartupUri |
Запуск приложения |
| Главное окно | Form |
Window |
Рамка с заголовком и кнопкой закрытия |
| Элемент UI | Label, Button, TextBox… |
То же + TextBlock, PasswordBox |
То, что видит пользователь |
| Событие | button.Click += .. |
Click="OnClick" в XAML |
Реакция на действие |
| Цикл | Application.Run(form) |
Внутри Application |
Программа жива, пока окно открыто |
| Диалог | MessageBox.Show(..) |
MessageBox.Show(..) |
Всплывающее сообщение поверх окна |
Пока цикл работает, код после Application.Run не выполняется — как mainloop() в Tkinter.
Словарь элементов за 30 секунд
| Элемент | WinForms | WPF | Зачем | Как прочитать значение |
|---|---|---|---|---|
| Окно | Form |
Window |
Главная рамка | — |
| Надпись | Label |
Label, TextBlock |
Статический текст | label.Text / {Binding} |
| Кнопка | Button |
Button |
Действие по клику | Click / command |
| Поле ввода | TextBox |
TextBox |
Одна строка | textBox.Text |
| Пароль | TextBox + UseSystemPasswordChar |
PasswordBox |
Скрытый ввод | PasswordBox.Password |
| Галочка | CheckBox |
CheckBox |
Вкл/выкл | Checked / IsChecked |
| Переключатель | RadioButton |
RadioButton |
Один из нескольких | Checked + группа |
| Список | ListBox |
ListBox |
To-do, выбор строки | SelectedIndex, Items |
| Меню | MenuStrip |
Menu |
Файл, Справка | обработчик пункта |
| Диалог | MessageBox.Show |
MessageBox.Show |
OK, Yes/No | возвращаемое значение |
Компоновка WinForms: Location + Size, Dock, Anchor, TableLayoutPanel.
Компоновка WPF: Grid, StackPanel, DockPanel — см. справочник XAML.
Обязательный каркас WinForms
Любой пример WinForms ниже повторяет эту структуру. Запомните её — как import tkinter и mainloop() в Tkinter.
Скопируйте в Program.cs целиком (после dotnet new winforms):
Разбор каркаса WinForms — по строкам
| Строка / блок | Смысл |
|---|---|
using System.Drawing; |
Типы Point, Size, Font, Color — координаты и оформление |
using System.Windows.Forms; |
Form, Button, Application, MessageBox |
namespace MyDesktopApp; |
Имя проекта из шаблона dotnet new; должно совпадать с .csproj |
[STAThread] |
Один UI-поток для COM и контролов Windows; без атрибута возможны странные ошибки |
ApplicationConfiguration.Initialize() |
Настройка DPI и стилей (.NET 6+); вызывают один раз в начале Main |
new Form { .. } |
Главное окно; Text — заголовок в строке заголовка ОС |
ClientSize = new Size(400, 300) |
Ширина × высота рабочей области без рамки окна |
StartPosition = CenterScreen |
Окно по центру монитора при старте |
Application.Run(form) |
Цикл сообщений; без этой строки окно мелькает и сразу закроется |
Файл проекта (шаблон создаёт сам):
<TargetFramework>net8.0-windows</TargetFramework>
<UseWindowsForms>true</UseWindowsForms>
Если указать net8.0 без -windows, типы Form и Application не найдутся при сборке.
Что попробовать: добавьте form.MaximizeBox = false; — исчезнет кнопка «развернуть».
Обязательный каркас WPF
WPF делит UI на разметку (XAML) и код (C#). Окно описывают в двух связанных файлах.
MainWindow.xaml — замените содержимое после dotnet new wpf:
<Window x:Class="MyWpfApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Моё приложение"
Height="300" Width="400"
WindowStartupLocation="CenterScreen">
<!-- Label, Button, TextBox — между открывающим и закрывающим Window -->
</Window>
MainWindow.xaml.cs:
namespace MyWpfApp;
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
App.xaml (шаблон, обычно не трогают):
<Application x:Class="MyWpfApp.App"
StartupUri="MainWindow.xaml">
</Application>
Разбор каркаса WPF — по частям
| Часть | Смысл |
|---|---|
x:Class="MyWpfApp.MainWindow" |
Связь XAML с классом MainWindow в MainWindow.xaml.cs; имя должно совпадать |
xmlns / xmlns:x |
Пространства имён XML — стандартные для WPF |
Title, Height, Width |
Заголовок и размер окна (в отличие от WinForms ClientSize) |
WindowStartupLocation="CenterScreen" |
Центрирование — аналог FormStartPosition.CenterScreen |
partial class MainWindow : Window |
Класс окна; partial — вторая часть генерируется из XAML |
InitializeComponent() |
Загружает XAML и создаёт поля для x:Name; не удаляйте |
StartupUri="MainWindow.xaml" |
Какое окно открыть при старте |
Что попробуйте: смените Title и перезапустите dotnet run — заголовок окна изменится без правки C#.
Стартовые окна
Простые примеры «с нуля» — с них. Каждый блок — полный рабочий код: скопируйте, вставьте, запустите.
Минимальное окно с меткой
Задача: показать, что C# на .NET умеет открыть окно с текстом — минимум для проверки установки SDK и сдачи отчёта «программа с GUI».
Что получится: окно по центру экрана с одной надписью «Окно работает!».
WinForms — полный Program.cs
Символ | разделяет пары «подпись — маска».
| Стек | Класс | Успешный результат |
|---|---|---|
| WinForms | System.Windows.Forms.OpenFileDialog |
DialogResult.OK |
| WPF | Microsoft.Win32.OpenFileDialog |
true |
4. Мини-калькулятор сложения (WinForms)
Задача: два TextBox, кнопка «=», результат в Label — связка ввода, события и TryParse.
Смысл: результат на форме, без MessageBox — пользователь видит ошибку «Ошибка» в том же окне. Расширение до -, *, / — один обработчик и switch по оператору.
5. Привязка данных в WPF (простой уровень)
Задача: текст «Привет, …!» обновляется сам, пока пользователь печатает в поле — задел под MVVM.
Models/Person.cs:
namespace MyWpfApp.Models;
public sealed class Person
{
public string Name { get; set; } = "Гость";
}
MainWindow.xaml:
<StackPanel Margin="20">
</StackPanel>
MainWindow.xaml.cs:
using MyWpfApp.Models;
public MainWindow()
{
InitializeComponent();
DataContext = new Person();
}
Разбор Binding
| Конструкция | Смысл |
|---|---|
DataContext = new Person() |
Объект-источник для всех {Binding ..} на окне |
{Binding Name} |
Свойство Person.Name |
StringFormat='Привет, {0}!' |
Шаблон отображения |
UpdateSourceTrigger=PropertyChanged |
Модель обновляется на каждый символ, не только при потере фокуса |
Два {Binding Name} |
Одно свойство — два контрола; WPF синхронизирует их |
В учебных проектах достаточно `DataContext` и простого класса.
В курсовой и production свойства выносят во ViewModel с `INotifyPropertyChanged` — см. Первая форма WPF — XAML, стили и шаблоны и практикум MVVM.
6. Подтверждение при закрытии окна
WinForms:
form.FormClosing += (_, e) =>
{
if (MessageBox.Show("Закрыть приложение?", "Выход",
MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No)
e.Cancel = true;
};
WPF — атрибут Closing="OnClosing" на Window и в обработчике e.Cancel = true при ответе No.
Смысл: крестик в заголовке по умолчанию закрывает окно сразу; Cancel = true отменяет закрытие — нужно для «Сохранить изменения?».
7. Шаблоны для своих проектов
Окно по центру
WinForms: StartPosition = FormStartPosition.CenterScreen.
WPF: WindowStartupLocation="CenterScreen".
Логика отдельно от формы
// Services/GreetingService.cs
public static class GreetingService
{
public static string Build(string name) =>
string.IsNullOrWhiteSpace(name) ? "Введите имя" : $"Здравствуй, {name.Trim()}!";
}
Кнопка вызывает GreetingService.Build(entry.Text) — форма остаётся тонкой; логику можно проверить unit-тестом без GUI. Это плюс на защите курсовой.
Частые ошибки и как исправить
| Симптом | Причина | Решение |
|---|---|---|
| Окно мелькает и закрывается | Нет Application.Run(form) |
Добавьте в конец Main перед закрывающей } |
| «Не найден тип Form» | TFM net8.0 без -windows |
В .csproj: net8.0-windows |
| Ошибка CS0246 Window / Form | Нет UseWindowsForms / UseWPF |
Флаги в .csproj из шаблона dotnet new |
| Контрол не виден | Нет Controls.Add |
Каждый контрол добавьте на form или в panel |
| Кнопка срабатывает при старте | Вызвали метод вместо ссылки | Click += Handler, не Click += Handler() |
| XAML: имя не существует | x:Class не совпадает с namespace |
MyApp.MainWindow в XAML = namespace MyApp + class MainWindow |
| UI «завис» на 5 секунд | Thread.Sleep или тяжёлый цикл в Click |
await Task.Run(..) — см. Особенности разработки десктопных приложений |
| InvalidOperationException | Обновление UI из фонового потока | WinForms: control.Invoke(() => ..); WPF: Dispatcher.Invoke |
25,5 не парсится |
Локаль Windows | .Replace(',', '.') + InvariantCulture в TryParse |
Маршрут изучения
| Шаг | Пример в статье | Зачем | Дальше |
|---|---|---|---|
| 1 | Каркас WinForms | Понять Application.Run |
Windows Forms (WinForms) — теория WinForms |
| 2 | Окно + кнопка | События и MessageBox | Справочник по WinForms — элементы UI — справочник UI |
| 3 | TextBox + конвертер | Ввод, парсинг, формула | Лабораторная «калькулятор» |
| 4 | ListBox to-do | Коллекция на форме | Курсовая «список задач» |
| 5 | WPF Binding | XAML и данные | Первая форма WPF — XAML, стили и шаблоны — WPF с нуля |
| 6 | Практикум MVVM | Клиент-сервер | TaskDesk |
См. также
- Windows Forms (WinForms) — теория и конструктор Visual Studio
- Первая форма WPF — XAML, стили, DataTemplate
- Справочник WinForms и справочник WPF
- Десктопные приложения — о разделе
- C# — о разделе
- Tkinter — окна и виджеты — те же задачи на Python
- Java Swing — окна и кнопки — те же задачи на Java
- Unity C# — скрипты — C# в игровом движке
- Шаблоны — минимальные каркасы проектов