Предыдущая лекция | | Следующая лекция
:----------------:|:----------:|:----------------:
[Библиотеки классов](./t7_dll.md) | [Содержание](../readme.md#тема-8-оконные-приложения) | [Ресурсы](./wpf_resource.md)
# Обзор типов оконных приложений в `C#`. Знакомство со структурой проекта `WPF/Avalonia`. Компоновка. Image.
>Содрано [отсюда](https://metanit.com/sharp/wpf/1.php)
* [Технологии создания оконных приложений](#технологии-создания-оконных-приложений)
* [Особенности платформ WPF/Avalonia](#особенности-платформ-wpfavalonia)
* [Установка Avalonia](#установка-avalonia)
* [Создание оконного приложения](#создание-оконного-приложения)
* [Структура проекта](#структура-проекта)
* [Компоновка](#компоновка)
* [Image. Ресурсы](#image-ресурсы)
## Технологии создания оконных приложений
В **C#** есть несколько технологий для созданий оконных приложений:
* **Windows Forms** - разработка "классических" приложений Windows, считается устаревшей
**Windows Forms** — интерфейс программирования приложений (API), отвечающий за графический интерфейс пользователя и являющийся частью *Microsoft .NET Framework*. Данный интерфейс упрощает доступ к элементам интерфейса Microsoft Windows за счет создания обёртки для существующего **Win32 API** в управляемом коде. Причём управляемый код — классы, реализующие API для **Windows Forms**, не зависят от языка разработки.
* **WPF** (Window Presentation Foundation) - более современный фреймворк для **.NET**, но заточен только под Windows (отрисовку реализует через **DirectX**)
* **UWP** (Universal Windows Platform) - вроде как "последний писк", рассчитанный на разработку универсальных приложений под Windows Phone, Windows 8 и.т.д
* **Avalonia** являеся практически калькой с **WPF**. Он совместим на уровне разметки, но отрисовка реализована через **OpenGL**.
## Особенности платформ WPF/Avalonia
Если при создании традиционных приложений на основе **Windows Forms** за отрисовку элементов управления и графики отвечали такие части ОС Windows, как **User32** и **GDI+**, то приложения **WPF** основаны на **DirectX** (**Avalonia**, соответственно, на **OpenGL**). В этом состоит ключевая особенность рендеринга графики: используя **WPF/Avalonia**, значительная часть работы по отрисовке графики, как простейших кнопочек, так и сложных 3D-моделей, ложиться на графический процессор на видеокарте, что также позволяет воспользоваться аппаратным ускорением графики.
Одной из важных особенностей является использование языка декларативной разметки интерфейса **XAML**, основанного на **XML**: вы можете создавать насыщенный графический интерфейс, используя или декларативное объявление интерфейса, или код **C#**, либо совмещать и то, и другое.
### Преимущества WPF/Avalonia
Что вам, как разработчику, предлагает **WPF/Avalonia**?
* Использование традиционных языков **.NET**-платформы - **C#** для создания логики приложения
* Возможность декларативного определения графического интерфейса с помощью специального языка разметки **XAML**, основанном на **XML** и представляющем альтернативу программному созданию графики и элементов управления, а также возможность комбинировать **XAML** и **C#**
* Независимость от разрешения экрана: поскольку в WPF/Avalonia все элементы измеряются в независимых от устройства единицах, приложения на WPF/Avalonia легко масштабируются под разные экраны с разным разрешением.
* Новые возможности, которых сложно было достичь в **Windows Forms**, например, создание трехмерных моделей, привязка данных, использование таких элементов, как стили, шаблоны, темы и др.
* Хорошее взаимодействие с **Windows Forms** (только **WPF**), благодаря чему, например, в приложениях **WPF** можно использовать традиционные элементы управления из **Windows Forms**.
* Богатые возможности по созданию различных приложений: это и мультимедиа, и двухмерная и трехмерная графика, и богатый набор встроенных элементов управления, а также возможность самим создавать новые элементы, создание анимаций, привязка данных, стили, шаблоны, темы и многое другое
* Аппаратное ускорение графики - вне зависимости от того, работаете ли вы с **2D** или **3D**, графикой или текстом, все компоненты приложения транслируются в объекты, понятные **Direct3D/OpenGL**, и затем визуализируются с помощью процессора на видеокарте, что повышает производительность, делает графику более плавной.
## Установка Avalonia
Avalonia мы использовать не будем, поэтому этот раздел можно пропустить
1. В основном окне **Rider** выбрать вкладку *Configure -> Plugins*:

И установите `AvaloniaRider` (в строке поиска введите "avalonia")
При установке может выдать сообщение, что плагин разработан не в **JetBrains** и использовать на свой страх - соглашаемся (**Accept**)
1. После установки плагина перезагрузите IDE и установите шаблоны проектов для **Avalonia**. В консоли выполните команду:
```
dotnet new install Avalonia.Templates
```
>Для .NET 6.0 и более ранних версий замените install на --install.
>Версию .NET можно узнать выполнив в консоли команду `dotnet --version`
## Создание оконного приложения
### Microsoft Visual Studio
Создайте новый проект "Приложение WPF (Майкрософт)"

По-умолчанию IDE Visual Studio разбито на 3 части:

* слева панель элементов - список визуальных элементов (кнопки, токстовые поля и т.п.)
* в центре основное окно, предназначенное для редактирования исходного кода. При отображении файлов XAML (читается как "замл") разбито на две части: визуальное отображение и текст разметки
* справа Обозреватель решений и структура проекта: Properties (Свойства); Ссылки (Зависимости); App.config - настройки проекта; App.xaml - разметка проекта и MainWindow.xaml - разметка окна.
Если каких-то панелей нет на экране, то можно их найти в меню Вид.
### Rider
Запустите **Rider** и создайте новое решение:
Если шаблоны установлены нормально, то в окне создания нового проекта появится секция *Other*:
Выберите **Avalonia .NET Core App**
### Настройка проекта
При создании задаете *Название решения*, *Имя проекта* и, если нужно, *Расположение*. Остальные параметры оставляем по-умолчанию.
>Название проекта должно отражать предметную область или название компании (за это есть отдельные баллы на чемпионате и демо-экзамене)
**Основные типы файлов проекта:**
* **XAML** eXtended Application Markup Languale - язык разметки, очень похож на XML. В таких файлах хранится описание внешнего вида окна.
* **.cs** - файлы с исходным кодом на C# для окна.
## Структура проекта
В структуре проекта **WPF** следует выделить следующие моменты. **Во-первых**, в проекте имеется файл `App.xaml` и связанный с ним файл кода `App.xaml.cs` - это глобальные файлы для всего приложения, позже мы о них поговорим подробнее. А пока только следует знать, что `App.xaml` задает файл окна программы, которое будет открываться при запуске приложения. Если вы откроете этот файл, то можете найти в нем строку `StartupUri="MainWindow.xaml"` - то есть в данном случае, когда мы запустим приложение, будет создаваться интерфейс из файла `MainWindow.xaml`.
Далее в структуре определены файл разметки `MainWindow.xaml` и файл связанного кода `MainWindow.xaml.cs`. Файл `MainWindow.xaml` и представляет определение окна приложение, которое мы увидим при запуске.
### Введение в язык XAML
**XAML** (eXtensible Application Markup Language) - язык разметки, используемый для инициализации объектов в технологиях на платформе **.NET**. Применительно к **WPF** данный язык используется прежде всего для создания пользовательского интерфейса декларативным путем, наподобие **HTML** в веб-программировании.
**XAML** - не является обязательной частью приложения, мы вобще можем обходиться без него, создавая все элементы в файле связанного с ним кода на языке **C#**. Однако использование **XAML** все-таки несет некоторые преимущества:
* Возможность отделить графический интерфейс от логики приложения, благодаря чему над разными частями приложения могут относительно автономно работать разные специалисты: над интерфейсом - дизайнеры, над кодом логики - программисты.
* Компактность, понятность, код на XAML относительно легко поддерживать.
При компиляции приложения в Visual Studio код в xaml-файлах также компилируется в бинарное представление кода xaml, которое называется BAML (Binary Application Markup Language). И затем код baml встраивается в финальную сборку приложения - exe или dll-файл.
#### Структура и пространства имен AXAML
При создании нового проекта **WPF** он уже содержит файлы с кодом xaml. Так, создаваемый по умолчанию в проекте файл `MainWindow.xaml` будет иметь следующую разметку:
```xml
```
Если вы совершенно не знакомы с **xaml** и с **xml**, то даже этот небольшой минимальный код окна может вызывать затруднения.
Подобно структуре веб-страничке на **html**, здесь есть некоторая иерархия элементов. Элементом верхнего уровня является тег **Window**, который представляет собой окно приложения. При создании других окон в приложении нам придется всегда начинать объявление интерфейса с элемента **Window**, поскольку это элемент самого верхнего уровня.
Кроме **Window** существует еще два элемента верхнего уровня:
* Page
* Application
Элемент **Window** имеет вложенный пустой элемент **Grid**, а также подобно html-элементам ряд атрибутов (_Title_, _Width_, _Height_) - они задают заголовок, ширину и высоту окна соответственно.
#### Пространства имен XAML
При создании кода на языке **C#**, чтобы нам были доступны определенные классы, мы подключаем пространства имен с помощью директивы `using`, например, `using System.Windows;`.
Чтобы задействовать элементы в **XAML**, мы также подключаем пространства имен. Вторая и третья строчки как раз и представляют собой пространства имен, подключаемые в проект по умолчанию. А атрибут _xmlns_ представляет специальный атрибут для определения пространства имен в **XML**.
Так, пространство имен `http://schemas.microsoft.com/winfx/2006/xaml/presentation` содержит описание и определение большинства элементов управления. Так как является пространством имен по умолчанию, то объявляется без всяких префиксов.
`http://schemas.microsoft.com/winfx/2006/xaml` - это пространство имен, которое определяет некоторые свойства **XAML**, например свойство _Name_ или _Key_. Используемый префикс `x` в определении `xmlns:x` означает, что те свойства элементов, которые заключены в этом пространстве имен, будут использоваться с префиксом `x` - `x:Name` или `x:Key`. Это же пространство имен используется уже в первой строчке `x:Class="XamlApp.MainWindow"` - здесь создается новый класс **MainWindow** и соответствующий ему файл кода, куда будет прописываться логика для данного окна приложения.
Это два основных пространства имен. Рассмотрим остальные:
`xmlns:d="http://schemas.microsoft.com/expression/blend/2008"`: предоставляет поддержку атрибутов в режиме дизайнера. Это пространство имен преимущественно предназначено для другого инструмента по созданию дизайна на XAML - Microsoft Expression Blend
`xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"`: обеспечивает режим совместимости разметок XAML. В определении объекта Window двумя строчками ниже можно найти его применение:
`xmlns:local="clr-namespace:XamlApp"`: пространство имен текущего проекта. Так как в нашем случае проект называется **XamlApp**, то простраство имен называется аналогично. И через префикс `local` я смогу получить в XAML различные объекты, которые я определил в проекте.
Важно понимать, что эти пространства имен не эквивалентны тем пространствам имен, которые подключаются при помощи директивы `using` в **c#**.
#### Элементы и их атрибуты
XAML предлагает очень простую и ясную схему определения различных элементов и их свойств. Каждый элемент, как и любой элемент XML, должен иметь открывающий и закрывающий теги, как в случае с элементом `Window`:
```xml
```
Либо элемент может иметь сокращенню форму с закрывающим слешем в конце, наподобие:
```xml
```
Но в отличие от элементов xml каждый элемент в XAML соответствует определенному классу **C#**. Например, элемент `Button` соответствует классу `System.Windows.Controls.Button`. А свойства этого класса соответствуют атрибутам элемента `Button`.
Например, добавим кнопку в создаваемую по умолчанию разметку окна:
```xml
```
Сначала идет элемент самого высшего уровня - **Window** (я содержимое вырезал, чтобы не засорять код) и в нем уже определен элемент **Button**, представляющий кнопку.
Для кнопки мы можем определить свойства в виде атрибутов. Здесь определены атрибуты `x:Name` (имя кнопки), `Width`, `Height` и `Content`.
Подобным образом мы можем определить и другие атрибуты, которые нам нужны. Либо мы можем не определять атрибуты, и тогда они будут использовать значения по умолчанию.
Определив разметку xaml, мы можем запустить проект, и нам отобразится графически весь код xaml - то есть наша кнопка.

#### Специальные символы
При определении интерфейса в XAML мы можем столкнуться с некоторыми ограничениями. В частности, мы не можем использовать специальные символы, такие как знак амперсанда `&`, кавычки `"` и угловые скобки `<` и `>`. Например, мы хотим, чтобы текст кнопки был следующим: `<"Hello">`. У кнопки есть свойство *Content*, которое задает содержимое кнопки. И можно предположить, что нам надо написать так:
```xml