|
@@ -2,7 +2,7 @@
|
|
|
:----------------:|:----------:|:----------------:
|
|
:----------------:|:----------:|:----------------:
|
|
|
[Библиотеки классов](./t7_dll.md) | [Содержание](../readme.md#тема-8-оконные-приложения) | [Ресурсы](./wpf_resource.md)
|
|
[Библиотеки классов](./t7_dll.md) | [Содержание](../readme.md#тема-8-оконные-приложения) | [Ресурсы](./wpf_resource.md)
|
|
|
|
|
|
|
|
-# Обзор типов оконных приложений в C#. Знакомство со структурой проекта WPF/Avalonia. Компоновка. Image. Ресурсы.
|
|
|
|
|
|
|
+# Обзор типов оконных приложений в `C#`. Знакомство со структурой проекта `WPF/Avalonia`. Компоновка. Image.
|
|
|
|
|
|
|
|
>Содрано [отсюда](https://metanit.com/sharp/wpf/1.php)
|
|
>Содрано [отсюда](https://metanit.com/sharp/wpf/1.php)
|
|
|
|
|
|
|
@@ -17,33 +17,31 @@
|
|
|
|
|
|
|
|
## Технологии создания оконных приложений
|
|
## Технологии создания оконных приложений
|
|
|
|
|
|
|
|
-В C# есть несколько технологий для созданий оконных приложений:
|
|
|
|
|
|
|
+В **C#** есть несколько технологий для созданий оконных приложений:
|
|
|
|
|
|
|
|
* **Windows Forms** - разработка "классических" приложений Windows, считается устаревшей
|
|
* **Windows Forms** - разработка "классических" приложений Windows, считается устаревшей
|
|
|
|
|
|
|
|
- **Windows Forms** — интерфейс программирования приложений (API), отвечающий за графический интерфейс пользователя и являющийся частью *Microsoft .NET Framework*. Данный интерфейс упрощает доступ к элементам интерфейса Microsoft Windows за счет создания обёртки для существующего *Win32 API* в управляемом коде. Причём управляемый код — классы, реализующие API для **Windows Forms**, не зависят от языка разработки.
|
|
|
|
|
|
|
+ **Windows Forms** — интерфейс программирования приложений (API), отвечающий за графический интерфейс пользователя и являющийся частью *Microsoft .NET Framework*. Данный интерфейс упрощает доступ к элементам интерфейса Microsoft Windows за счет создания обёртки для существующего **Win32 API** в управляемом коде. Причём управляемый код — классы, реализующие API для **Windows Forms**, не зависят от языка разработки.
|
|
|
|
|
|
|
|
-* WPF (Window Presentation Foundation) - более современный фреймворк для .NET Framework, но заточен только под Windows (отрисовку реализует через **DirectX**)
|
|
|
|
|
|
|
+* **WPF** (Window Presentation Foundation) - более современный фреймворк для **.NET**, но заточен только под Windows (отрисовку реализует через **DirectX**)
|
|
|
|
|
|
|
|
- >Стоит отметить, что *.NET Framework* считается устаревшей технологией и на смену ей пришла кроссплатформенная библиотека *.NET Core*. Для неё есть аналог **WPF** - **Avalonia**, совместимый, на уровне разметки, фреймворк, работающий на **OpenGL**.
|
|
|
|
|
|
|
+* **UWP** (Universal Windows Platform) - вроде как "последний писк", рассчитанный на разработку универсальных приложений под Windows Phone, Windows 8 и.т.д
|
|
|
|
|
|
|
|
-* UWP (Universal Windows Platform) - вроде как "последний писк", рассчитанный на разработку универсальных приложений под Windows Phone, Windows 8 и.т.д
|
|
|
|
|
-
|
|
|
|
|
-**Avalonia** являеся практически калькой с **WPF**, поэтому далее я их рассматриваю одновременно.
|
|
|
|
|
|
|
+* **Avalonia** являеся практически калькой с **WPF**. Он совместим на уровне разметки, но отрисовка реализована через **OpenGL**.
|
|
|
|
|
|
|
|
## Особенности платформ WPF/Avalonia
|
|
## Особенности платформ WPF/Avalonia
|
|
|
|
|
|
|
|
Если при создании традиционных приложений на основе **Windows Forms** за отрисовку элементов управления и графики отвечали такие части ОС Windows, как **User32** и **GDI+**, то приложения **WPF** основаны на **DirectX** (**Avalonia**, соответственно, на **OpenGL**). В этом состоит ключевая особенность рендеринга графики: используя **WPF/Avalonia**, значительная часть работы по отрисовке графики, как простейших кнопочек, так и сложных 3D-моделей, ложиться на графический процессор на видеокарте, что также позволяет воспользоваться аппаратным ускорением графики.
|
|
Если при создании традиционных приложений на основе **Windows Forms** за отрисовку элементов управления и графики отвечали такие части ОС Windows, как **User32** и **GDI+**, то приложения **WPF** основаны на **DirectX** (**Avalonia**, соответственно, на **OpenGL**). В этом состоит ключевая особенность рендеринга графики: используя **WPF/Avalonia**, значительная часть работы по отрисовке графики, как простейших кнопочек, так и сложных 3D-моделей, ложиться на графический процессор на видеокарте, что также позволяет воспользоваться аппаратным ускорением графики.
|
|
|
|
|
|
|
|
-Одной из важных особенностей является использование языка декларативной разметки интерфейса XAML, основанного на XML: вы можете создавать насыщенный графический интерфейс, используя или декларативное объявление интерфейса, или код C#, либо совмещать и то, и другое.
|
|
|
|
|
|
|
+Одной из важных особенностей является использование языка декларативной разметки интерфейса **XAML**, основанного на **XML**: вы можете создавать насыщенный графический интерфейс, используя или декларативное объявление интерфейса, или код **C#**, либо совмещать и то, и другое.
|
|
|
|
|
|
|
|
### Преимущества WPF/Avalonia
|
|
### Преимущества WPF/Avalonia
|
|
|
|
|
|
|
|
Что вам, как разработчику, предлагает **WPF/Avalonia**?
|
|
Что вам, как разработчику, предлагает **WPF/Avalonia**?
|
|
|
|
|
|
|
|
-* Использование традиционных языков .NET-платформы - C# для создания логики приложения
|
|
|
|
|
|
|
+* Использование традиционных языков **.NET**-платформы - **C#** для создания логики приложения
|
|
|
|
|
|
|
|
-* Возможность декларативного определения графического интерфейса с помощью специального языка разметки XAML, основанном на XML и представляющем альтернативу программному созданию графики и элементов управления, а также возможность комбинировать XAML и C#
|
|
|
|
|
|
|
+* Возможность декларативного определения графического интерфейса с помощью специального языка разметки **XAML**, основанном на **XML** и представляющем альтернативу программному созданию графики и элементов управления, а также возможность комбинировать **XAML** и **C#**
|
|
|
|
|
|
|
|
* Независимость от разрешения экрана: поскольку в WPF/Avalonia все элементы измеряются в независимых от устройства единицах, приложения на WPF/Avalonia легко масштабируются под разные экраны с разным разрешением.
|
|
* Независимость от разрешения экрана: поскольку в WPF/Avalonia все элементы измеряются в независимых от устройства единицах, приложения на WPF/Avalonia легко масштабируются под разные экраны с разным разрешением.
|
|
|
|
|
|
|
@@ -53,11 +51,11 @@
|
|
|
|
|
|
|
|
* Богатые возможности по созданию различных приложений: это и мультимедиа, и двухмерная и трехмерная графика, и богатый набор встроенных элементов управления, а также возможность самим создавать новые элементы, создание анимаций, привязка данных, стили, шаблоны, темы и многое другое
|
|
* Богатые возможности по созданию различных приложений: это и мультимедиа, и двухмерная и трехмерная графика, и богатый набор встроенных элементов управления, а также возможность самим создавать новые элементы, создание анимаций, привязка данных, стили, шаблоны, темы и многое другое
|
|
|
|
|
|
|
|
-* Аппаратное ускорение графики - вне зависимости от того, работаете ли вы с 2D или 3D, графикой или текстом, все компоненты приложения транслируются в объекты, понятные Direct3D/OpenGL, и затем визуализируются с помощью процессора на видеокарте, что повышает производительность, делает графику более плавной.
|
|
|
|
|
|
|
+* Аппаратное ускорение графики - вне зависимости от того, работаете ли вы с **2D** или **3D**, графикой или текстом, все компоненты приложения транслируются в объекты, понятные **Direct3D/OpenGL**, и затем визуализируются с помощью процессора на видеокарте, что повышает производительность, делает графику более плавной.
|
|
|
|
|
|
|
|
## Установка Avalonia
|
|
## Установка Avalonia
|
|
|
|
|
|
|
|
-Далее мы будем использовать Avalonia, но так как он не входит в .NET, то нужно его установить:
|
|
|
|
|
|
|
+Avalonia мы использовать не будем, поэтому этот раздел можно пропустить
|
|
|
|
|
|
|
|
1. В основном окне **Rider** выбрать вкладку *Configure -> Plugins*:
|
|
1. В основном окне **Rider** выбрать вкладку *Configure -> Plugins*:
|
|
|
|
|
|
|
@@ -78,93 +76,116 @@
|
|
|
|
|
|
|
|
## Создание оконного приложения
|
|
## Создание оконного приложения
|
|
|
|
|
|
|
|
|
|
+### Microsoft Visual Studio
|
|
|
|
|
+
|
|
|
|
|
+Создайте новый проект "Приложение WPF (Майкрософт)"
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+По-умолчанию IDE Visual Studio разбито на 3 части:
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+* слева панель элементов - список визуальных элементов (кнопки, токстовые поля и т.п.)
|
|
|
|
|
+* в центре основное окно, предназначенное для редактирования исходного кода. При отображении файлов XAML (читается как "замл") разбито на две части: визуальное отображение и текст разметки
|
|
|
|
|
+* справа Обозреватель решений и структура проекта: Properties (Свойства); Ссылки (Зависимости); App.config - настройки проекта; App.xaml - разметка проекта и MainWindow.xaml - разметка окна.
|
|
|
|
|
+
|
|
|
|
|
+Если каких-то панелей нет на экране, то можно их найти в меню Вид.
|
|
|
|
|
+
|
|
|
|
|
+### Rider
|
|
|
|
|
+
|
|
|
Запустите **Rider** и создайте новое решение:
|
|
Запустите **Rider** и создайте новое решение:
|
|
|
|
|
|
|
|
Если шаблоны установлены нормально, то в окне создания нового проекта появится секция *Other*:
|
|
Если шаблоны установлены нормально, то в окне создания нового проекта появится секция *Other*:
|
|
|
|
|
|
|
|
Выберите **Avalonia .NET Core App**
|
|
Выберите **Avalonia .NET Core App**
|
|
|
|
|
|
|
|
|
|
+### Настройка проекта
|
|
|
|
|
+
|
|
|
При создании задаете *Название решения*, *Имя проекта* и, если нужно, *Расположение*. Остальные параметры оставляем по-умолчанию.
|
|
При создании задаете *Название решения*, *Имя проекта* и, если нужно, *Расположение*. Остальные параметры оставляем по-умолчанию.
|
|
|
|
|
|
|
|
>Название проекта должно отражать предметную область или название компании (за это есть отдельные баллы на чемпионате и демо-экзамене)
|
|
>Название проекта должно отражать предметную область или название компании (за это есть отдельные баллы на чемпионате и демо-экзамене)
|
|
|
|
|
|
|
|
**Основные типы файлов проекта:**
|
|
**Основные типы файлов проекта:**
|
|
|
|
|
|
|
|
-* **.AXAML** (Avalonia eXtended Application Markup Languale) - язык разметки, очень похож на XML. В таких файлах хранится описание внешнего вида окна.
|
|
|
|
|
|
|
+* **XAML** eXtended Application Markup Languale - язык разметки, очень похож на XML. В таких файлах хранится описание внешнего вида окна.
|
|
|
* **.cs** - файлы с исходным кодом на C# для окна.
|
|
* **.cs** - файлы с исходным кодом на C# для окна.
|
|
|
|
|
|
|
|
## Структура проекта
|
|
## Структура проекта
|
|
|
|
|
|
|
|
-В структуре проекта следует выделить следующие моменты:
|
|
|
|
|
-
|
|
|
|
|
-**Во-первых**, в проекте имеется файл `App.axaml` и связанный с ним файл кода `App.axaml.cs` - это глобальные файлы для всего приложения, позже мы о них поговорим подробнее. А пока только следует знать, что в `App.axaml.cs` задается класс главного окна программы, которое будет открываться при запуске приложения. Если вы откроете этот файл, то можете найти в нем строку `desktop.MainWindow = new MainWindow();` - то есть в данном случае, когда мы запустим приложение, главным будет окно из класса `MainWindow`.
|
|
|
|
|
|
|
+В структуре проекта **WPF** следует выделить следующие моменты. **Во-первых**, в проекте имеется файл `App.xaml` и связанный с ним файл кода `App.xaml.cs` - это глобальные файлы для всего приложения, позже мы о них поговорим подробнее. А пока только следует знать, что `App.xaml` задает файл окна программы, которое будет открываться при запуске приложения. Если вы откроете этот файл, то можете найти в нем строку `StartupUri="MainWindow.xaml"` - то есть в данном случае, когда мы запустим приложение, будет создаваться интерфейс из файла `MainWindow.xaml`.
|
|
|
|
|
|
|
|
-Далее в структуре определены файл разметки `MainWindow.axaml` и файл связанного кода `MainWindow.axaml.cs`. Файл `MainWindow.axaml` и представляет определение окна приложения, которое мы увидим при запуске.
|
|
|
|
|
|
|
+Далее в структуре определены файл разметки `MainWindow.xaml` и файл связанного кода `MainWindow.xaml.cs`. Файл `MainWindow.xaml` и представляет определение окна приложение, которое мы увидим при запуске.
|
|
|
|
|
|
|
|
### Введение в язык XAML
|
|
### Введение в язык XAML
|
|
|
|
|
|
|
|
-**AXAML (Avalonia eXtensible Application Markup Language)** - язык разметки, используемый для инициализации объектов в технологиях на платформе .NET. Применительно к **Avalonia** данный язык используется прежде всего для создания пользовательского интерфейса декларативным путем, наподобие HTML в веб-программировании.
|
|
|
|
|
|
|
+**XAML** (eXtensible Application Markup Language) - язык разметки, используемый для инициализации объектов в технологиях на платформе **.NET**. Применительно к **WPF** данный язык используется прежде всего для создания пользовательского интерфейса декларативным путем, наподобие **HTML** в веб-программировании.
|
|
|
|
|
|
|
|
-**AXAML** - не является обязательной частью приложения, мы вобще можем обходиться без него, создавая все элементы в файле связанного с ним кода на языке C#. Однако использование AXAML все-таки несет некоторые преимущества:
|
|
|
|
|
|
|
+**XAML** - не является обязательной частью приложения, мы вобще можем обходиться без него, создавая все элементы в файле связанного с ним кода на языке **C#**. Однако использование **XAML** все-таки несет некоторые преимущества:
|
|
|
|
|
|
|
|
* Возможность отделить графический интерфейс от логики приложения, благодаря чему над разными частями приложения могут относительно автономно работать разные специалисты: над интерфейсом - дизайнеры, над кодом логики - программисты.
|
|
* Возможность отделить графический интерфейс от логики приложения, благодаря чему над разными частями приложения могут относительно автономно работать разные специалисты: над интерфейсом - дизайнеры, над кодом логики - программисты.
|
|
|
|
|
|
|
|
-* Компактность, понятность, код на AXAML относительно легко поддерживать.
|
|
|
|
|
|
|
+* Компактность, понятность, код на XAML относительно легко поддерживать.
|
|
|
|
|
|
|
|
-При компиляции приложения код в axaml-файлах также компилируется в бинарное представление кода axaml. И затем это бинарное представление встраивается в финальную сборку приложения - exe или dll-файл.
|
|
|
|
|
|
|
+При компиляции приложения в Visual Studio код в xaml-файлах также компилируется в бинарное представление кода xaml, которое называется BAML (Binary Application Markup Language). И затем код baml встраивается в финальную сборку приложения - exe или dll-файл.
|
|
|
|
|
|
|
|
#### Структура и пространства имен AXAML
|
|
#### Структура и пространства имен AXAML
|
|
|
|
|
|
|
|
-При создании нового проекта он уже содержит файлы с кодом axaml. Так, создаваемый по умолчанию в проекте файл `MainWindow.axaml` будет иметь следующую разметку:
|
|
|
|
|
|
|
+При создании нового проекта **WPF** он уже содержит файлы с кодом xaml. Так, создаваемый по умолчанию в проекте файл `MainWindow.xaml` будет иметь следующую разметку:
|
|
|
|
|
|
|
|
```xml
|
|
```xml
|
|
|
<Window
|
|
<Window
|
|
|
- xmlns="https://github.com/avaloniaui"
|
|
|
|
|
|
|
+ x:Class="XamlApp.MainWindow"
|
|
|
|
|
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
|
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
|
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
|
|
- mc:Ignorable="d"
|
|
|
|
|
- d:DesignWidth="800"
|
|
|
|
|
- d:DesignHeight="450"
|
|
|
|
|
- x:Class="AvaloniaFirst.MainWindow"
|
|
|
|
|
- Title="AvaloniaFirst"
|
|
|
|
|
|
|
+ xmlns:local="clr-namespace:XamlApp"
|
|
|
|
|
+ mc:Ignorable="d"
|
|
|
|
|
+ Title="MainWindow"
|
|
|
|
|
+ Height="350"
|
|
|
|
|
+ Width="525"
|
|
|
>
|
|
>
|
|
|
- Welcome to Avalonia!
|
|
|
|
|
|
|
+ <Grid>
|
|
|
|
|
+
|
|
|
|
|
+ </Grid>
|
|
|
</Window>
|
|
</Window>
|
|
|
```
|
|
```
|
|
|
|
|
|
|
|
-Если вы совершенно не знакомы с axaml и с xml, то даже этот небольшой минимальный код окна может вызывать затруднения.
|
|
|
|
|
|
|
+Если вы совершенно не знакомы с **xaml** и с **xml**, то даже этот небольшой минимальный код окна может вызывать затруднения.
|
|
|
|
|
|
|
|
-Подобно структуре веб-страничке на html, здесь есть некоторая иерархия элементов. Элементом верхнего уровня является тег **Window**, который представляет собой окно приложения. При создании других окон в приложении нам придется всегда начинать объявление интерфейса с элемента **Window**, поскольку это элемент самого верхнего уровня.
|
|
|
|
|
|
|
+Подобно структуре веб-страничке на **html**, здесь есть некоторая иерархия элементов. Элементом верхнего уровня является тег **Window**, который представляет собой окно приложения. При создании других окон в приложении нам придется всегда начинать объявление интерфейса с элемента **Window**, поскольку это элемент самого верхнего уровня.
|
|
|
|
|
|
|
|
Кроме **Window** существует еще два элемента верхнего уровня:
|
|
Кроме **Window** существует еще два элемента верхнего уровня:
|
|
|
|
|
|
|
|
* Page
|
|
* Page
|
|
|
* Application
|
|
* Application
|
|
|
|
|
|
|
|
-Элемент **Window** имеет вложенный текст (Welcome to Avalonia!), а также подобно html-элементам ряд атрибутов (*Title*, *DesignWidth*, *DesignHeight*) - они задают заголовок, ширину и высоту окна соответственно.
|
|
|
|
|
|
|
+Элемент **Window** имеет вложенный пустой элемент **Grid**, а также подобно html-элементам ряд атрибутов (_Title_, _Width_, _Height_) - они задают заголовок, ширину и высоту окна соответственно.
|
|
|
|
|
|
|
|
-#### Пространства имен AXAML
|
|
|
|
|
|
|
+#### Пространства имен XAML
|
|
|
|
|
|
|
|
-При создании кода на языке C#, чтобы нам были доступны определенные классы, мы подключаем пространства имен с помощью директивы using, например, `using Avalonia.Controls;`.
|
|
|
|
|
|
|
+При создании кода на языке **C#**, чтобы нам были доступны определенные классы, мы подключаем пространства имен с помощью директивы `using`, например, `using System.Windows;`.
|
|
|
|
|
|
|
|
-Чтобы задействовать элементы в AXAML, мы также подключаем пространства имен. Аттрибуты **xmlns** как раз и представляют собой пространства имен, подключаемые в проект.
|
|
|
|
|
|
|
+Чтобы задействовать элементы в **XAML**, мы также подключаем пространства имен. Вторая и третья строчки как раз и представляют собой пространства имен, подключаемые в проект по умолчанию. А атрибут _xmlns_ представляет специальный атрибут для определения пространства имен в **XML**.
|
|
|
|
|
|
|
|
-Так, пространство имен **https://github.com/avaloniaui** содержит описание и определение большинства элементов управления. Так как является пространством имен по умолчанию, то объявляется без всяких префиксов.
|
|
|
|
|
|
|
+Так, пространство имен `http://schemas.microsoft.com/winfx/2006/xaml/presentation` содержит описание и определение большинства элементов управления. Так как является пространством имен по умолчанию, то объявляется без всяких префиксов.
|
|
|
|
|
|
|
|
-**http://schemas.microsoft.com/winfx/2006/xaml** - это пространство имен, которое определяет некоторые свойства AXAML, например свойство _Name_ или _Key_. Используемый префикс `x` в определении `xmlns:x` означает, что те свойства элементов, которые заключены в этом пространстве имен, будут использоваться с префиксом x - `x:Name` или `x:Key`. Это же пространство имен используется уже в аттрибуте `x:Class="AvaloniaFirst.MainWindow"` - здесь создается ссылка на класс **MainWindow** и соответствующий ему файл кода, куда будет прописываться логика для данного окна приложения.
|
|
|
|
|
|
|
+`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:d="http://schemas.microsoft.com/expression/blend/2008"`: предоставляет поддержку атрибутов в режиме дизайнера. Это пространство имен преимущественно предназначено для другого инструмента по созданию дизайна на XAML - Microsoft Expression Blend
|
|
|
|
|
|
|
|
-**xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"**: обеспечивает режим совместимости разметок XAML.
|
|
|
|
|
|
|
+`xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"`: обеспечивает режим совместимости разметок XAML. В определении объекта Window двумя строчками ниже можно найти его применение:
|
|
|
|
|
|
|
|
-Важно понимать, что эти пространства имен не эквивалентны тем пространствам имен, которые подключаются при помощи директивы **using** в c#.
|
|
|
|
|
|
|
+`xmlns:local="clr-namespace:XamlApp"`: пространство имен текущего проекта. Так как в нашем случае проект называется **XamlApp**, то простраство имен называется аналогично. И через префикс `local` я смогу получить в XAML различные объекты, которые я определил в проекте.
|
|
|
|
|
+
|
|
|
|
|
+Важно понимать, что эти пространства имен не эквивалентны тем пространствам имен, которые подключаются при помощи директивы `using` в **c#**.
|
|
|
|
|
|
|
|
#### Элементы и их атрибуты
|
|
#### Элементы и их атрибуты
|
|
|
|
|
|
|
|
-XAML предлагает очень простую и ясную схему определения различных элементов и их свойств. Каждый элемент, как и любой элемент XML, должен иметь открывающий и закрывающий теги, как в случае с элементом Window:
|
|
|
|
|
|
|
+XAML предлагает очень простую и ясную схему определения различных элементов и их свойств. Каждый элемент, как и любой элемент XML, должен иметь открывающий и закрывающий теги, как в случае с элементом `Window`:
|
|
|
|
|
|
|
|
```xml
|
|
```xml
|
|
|
<Window></Window>
|
|
<Window></Window>
|
|
@@ -176,7 +197,7 @@ XAML предлагает очень простую и ясную схему о
|
|
|
<Window />
|
|
<Window />
|
|
|
```
|
|
```
|
|
|
|
|
|
|
|
-Но в отличие от элементов xml каждый элемент в XAML соответствует определенному классу C#. Например, элемент **Button** соответствует классу **Avalonia.Controls.Button**. А свойства этого класса соответствуют атрибутам элемента **Button**.
|
|
|
|
|
|
|
+Но в отличие от элементов xml каждый элемент в XAML соответствует определенному классу **C#**. Например, элемент `Button` соответствует классу `System.Windows.Controls.Button`. А свойства этого класса соответствуют атрибутам элемента `Button`.
|
|
|
|
|
|
|
|
Например, добавим кнопку в создаваемую по умолчанию разметку окна:
|
|
Например, добавим кнопку в создаваемую по умолчанию разметку окна:
|
|
|
|
|
|
|
@@ -249,30 +270,29 @@ XAML предлагает очень простую и ясную схему о
|
|
|
|
|
|
|
|
### Файлы отделённого кода
|
|
### Файлы отделённого кода
|
|
|
|
|
|
|
|
-При создании нового проекта в дополнение к создаваемому файлу `MainWindow.axaml` создается также файл отделённого кода `MainWindow.axaml.cs`, где, как предполагается, должна находится логика приложения связанная с разметкой из `MainWindow.axaml`. Файлы XAML позволяют нам определить интерфейс окна, но для создания логики приложения, например, для определения обработчиков событий элементов управления, нам все равно придется воспользоваться кодом C#.
|
|
|
|
|
|
|
+При создании нового проекта в дополнение к создаваемому файлу `MainWindow.xaml` создается также файл отделённого кода `MainWindow.xaml.cs`, где, как предполагается, должна находится логика приложения связанная с разметкой из `MainWindow.xaml`. Файлы XAML позволяют нам определить интерфейс окна, но для создания логики приложения, например, для определения обработчиков событий элементов управления, нам все равно придется воспользоваться кодом **C#**.
|
|
|
|
|
|
|
|
По умолчанию в разметке окна используется атрибут `x:Class`:
|
|
По умолчанию в разметке окна используется атрибут `x:Class`:
|
|
|
|
|
|
|
|
```xml
|
|
```xml
|
|
|
<Window
|
|
<Window
|
|
|
- x:Class="AvaloniaFirst.MainWindow"
|
|
|
|
|
|
|
+ x:Class="XamlApp.MainWindow"
|
|
|
...
|
|
...
|
|
|
```
|
|
```
|
|
|
|
|
|
|
|
-Атрибут `x:Class` указывает на класс, который будет представлять данное окно и в который будет компилироваться код в XAML при компиляции. То есть во время компиляции будет генерироваться класс **AvaloniaFirst.MainWindow**, унаследованный от класса **Avalonia.Controls**.
|
|
|
|
|
|
|
+Атрибут `x:Class` указывает на класс, который будет представлять данное окно и в который будет компилироваться код в XAML при компиляции. То есть во время компиляции будет генерироваться класс **XamlApp.MainWindow**, унаследованный от класса **System.Windows.Window**.
|
|
|
|
|
|
|
|
-Кроме того в файле отделенного кода `MainWindow.axaml.cs`, который **Rider** создает автоматически, мы также можем найти класс с тем же именем - в данном случае класс **MainWindow**. По умолчанию он имеет некоторый код:
|
|
|
|
|
|
|
+Кроме того в файле отделенного кода `MainWindow.xaml.cs`, который **Visual Studio** создает автоматически, мы также можем найти класс с тем же именем - в данном случае класс `XamlApp.MainWindow`. По умолчанию он имеет некоторый код:
|
|
|
|
|
|
|
|
```cs
|
|
```cs
|
|
|
-using Avalonia.Controls;
|
|
|
|
|
-
|
|
|
|
|
-namespace AvaloniaFirst;
|
|
|
|
|
-
|
|
|
|
|
-public partial class MainWindow : Window
|
|
|
|
|
|
|
+namespace XamlApp
|
|
|
{
|
|
{
|
|
|
- public MainWindow()
|
|
|
|
|
|
|
+ public partial class MainWindow : Window
|
|
|
{
|
|
{
|
|
|
- InitializeComponent();
|
|
|
|
|
|
|
+ public MainWindow()
|
|
|
|
|
+ {
|
|
|
|
|
+ InitializeComponent();
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
```
|
|
```
|
|
@@ -285,14 +305,14 @@ public partial class MainWindow : Window
|
|
|
|
|
|
|
|
В приложении часто требуется обратиться к какому-нибудь элементу управления. Для этого надо установить у элемента в XAML свойство **Name**.
|
|
В приложении часто требуется обратиться к какому-нибудь элементу управления. Для этого надо установить у элемента в XAML свойство **Name**.
|
|
|
|
|
|
|
|
-Еще одной точкой взаимодействия между xaml и C# являются события. С помощью атрибутов в XAML мы можем задать события, которые будут связанны с обработчиками в коде C#.
|
|
|
|
|
|
|
+Еще одной точкой взаимодействия между **xaml** и **C#** являются события. С помощью атрибутов в **XAML** мы можем задать события, которые будут связанны с обработчиками в коде **C#**.
|
|
|
|
|
|
|
|
Итак, в разметке главного окна определим два элемента: кнопку и текстовое поле.
|
|
Итак, в разметке главного окна определим два элемента: кнопку и текстовое поле.
|
|
|
|
|
|
|
|
>В теге **Window** может быть только один вложенный элемент. Обычно используют **Grid** (подробнее о нём поговорим ниже)
|
|
>В теге **Window** может быть только один вложенный элемент. Обычно используют **Grid** (подробнее о нём поговорим ниже)
|
|
|
|
|
|
|
|
```xml
|
|
```xml
|
|
|
-<Grid>
|
|
|
|
|
|
|
+<Grid x:Name="grid1">
|
|
|
<TextBox
|
|
<TextBox
|
|
|
x:Name="textBox1"
|
|
x:Name="textBox1"
|
|
|
Width="150"
|
|
Width="150"
|
|
@@ -304,43 +324,39 @@ public partial class MainWindow : Window
|
|
|
Width="100"
|
|
Width="100"
|
|
|
Height="30"
|
|
Height="30"
|
|
|
Content="Кнопка"
|
|
Content="Кнопка"
|
|
|
- Click="Button1_OnClick" />
|
|
|
|
|
|
|
+ Click="Button_Click" />
|
|
|
</Grid>
|
|
</Grid>
|
|
|
```
|
|
```
|
|
|
|
|
|
|
|
-И изменим класс **MainWindow** добавив в него обработчик нажатия кнопки *Button1_OnClick*:
|
|
|
|
|
|
|
+И изменим класс **MainWindow** добавив в него обработчик нажатия кнопки *Button_Click*:
|
|
|
|
|
|
|
|
```cs
|
|
```cs
|
|
|
-public partial class MainWindow : Window
|
|
|
|
|
|
|
+namespace XamlApp
|
|
|
{
|
|
{
|
|
|
- public MainWindow()
|
|
|
|
|
|
|
+ public partial class MainWindow : Window
|
|
|
{
|
|
{
|
|
|
- InitializeComponent();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private void Button1_OnClick(
|
|
|
|
|
- object? sender,
|
|
|
|
|
- RoutedEventArgs e)
|
|
|
|
|
- {
|
|
|
|
|
- string text = textBox1.Text;
|
|
|
|
|
- if (text != "")
|
|
|
|
|
|
|
+ public MainWindow()
|
|
|
|
|
+ {
|
|
|
|
|
+ InitializeComponent();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void Button_Click(
|
|
|
|
|
+ object sender,
|
|
|
|
|
+ RoutedEventArgs e)
|
|
|
{
|
|
{
|
|
|
- MessageBoxManager
|
|
|
|
|
- .GetMessageBoxStandard(
|
|
|
|
|
- "Caption",
|
|
|
|
|
- text,
|
|
|
|
|
- ButtonEnum.Ok)
|
|
|
|
|
- .ShowAsync();
|
|
|
|
|
|
|
+ string text = textBox1.Text;
|
|
|
|
|
+ if (text != "")
|
|
|
|
|
+ {
|
|
|
|
|
+ MessageBox.Show(text);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
```
|
|
```
|
|
|
|
|
|
|
|
->В **Avalonia** нет встроенного класса **MessageBox**. Нужно через **NuGet** установить библиотеку `MessageBox.Avalonia`
|
|
|
|
|
-
|
|
|
|
|
Определив имена элементов в XAML, затем мы можем к ним обращаться в коде c#: `var text = textBox1.Text`.
|
|
Определив имена элементов в XAML, затем мы можем к ним обращаться в коде c#: `var text = textBox1.Text`.
|
|
|
|
|
|
|
|
-В обработчике нажатия кнопки просто выводится сообщение, введенное в текстовое поле. После определения обработчика мы его можем связать с событием нажатия кнопки в xaml через атрибут _Click_: `Click="Button1_OnClick"`. В результате после нажатия на кнопку мы увидим в окне введенное в текстовое поле сообщение.
|
|
|
|
|
|
|
+В обработчике нажатия кнопки просто выводится сообщение, введенное в текстовое поле. После определения обработчика мы его можем связать с событием нажатия кнопки в xaml через атрибут _Click_: `Click="Button_Click"`. В результате после нажатия на кнопку мы увидим в окне введенное в текстовое поле сообщение.
|
|
|
|
|
|
|
|
#### Пространства имен из C# в XAML
|
|
#### Пространства имен из C# в XAML
|
|
|
|
|
|
|
@@ -351,14 +367,12 @@ public partial class MainWindow : Window
|
|
|
```xml
|
|
```xml
|
|
|
<Window
|
|
<Window
|
|
|
...
|
|
...
|
|
|
- xmlns:local="clr-namespace:AvaloniaFirst"
|
|
|
|
|
|
|
+ xmlns:local="clr-namespace:XamlApp"
|
|
|
```
|
|
```
|
|
|
|
|
|
|
|
Локальное пространство имен позволяет подключить все классы, которые определены в коде C# в нашем проекте. Например, добавим в проект следующий класс (напоминаю правило: каждый класс создаётся в отдельном файле):
|
|
Локальное пространство имен позволяет подключить все классы, которые определены в коде C# в нашем проекте. Например, добавим в проект следующий класс (напоминаю правило: каждый класс создаётся в отдельном файле):
|
|
|
|
|
|
|
|
```cs
|
|
```cs
|
|
|
-namespace AvaloniaFirst;
|
|
|
|
|
-
|
|
|
|
|
public class Phone
|
|
public class Phone
|
|
|
{
|
|
{
|
|
|
public string Name { get; set; }
|
|
public string Name { get; set; }
|
|
@@ -374,22 +388,27 @@ public class Phone
|
|
|
Используем этот класс в коде xaml:
|
|
Используем этот класс в коде xaml:
|
|
|
|
|
|
|
|
```xml
|
|
```xml
|
|
|
-<Button
|
|
|
|
|
- x:Name="phoneButton"
|
|
|
|
|
- Width="250"
|
|
|
|
|
- Height="40"
|
|
|
|
|
|
|
+<Grid x:Name="layoutGrid">
|
|
|
|
|
+ <Button
|
|
|
|
|
+ x:Name="phoneButton"
|
|
|
|
|
+ Width="250"
|
|
|
|
|
+ Height="40"
|
|
|
|
|
+ HorizontalAlignment="Center"
|
|
|
>
|
|
>
|
|
|
- <local:Phone
|
|
|
|
|
- Name="Lumia 950"
|
|
|
|
|
- Price="700" />
|
|
|
|
|
-</Button>
|
|
|
|
|
|
|
+ <Button.Content>
|
|
|
|
|
+ <local:Phone
|
|
|
|
|
+ Name="Lumia 950"
|
|
|
|
|
+ Price="700" />
|
|
|
|
|
+ </Button.Content>
|
|
|
|
|
+ </Button>
|
|
|
|
|
+</Grid>
|
|
|
```
|
|
```
|
|
|
|
|
|
|
|
Так как пространство имен проекта проецируется на префикс `local`, то все классы проекта можно использовать в форме `local:Название_Класса`. Так в данном случае в качестве содержимого кнопки устанавливается объект **Phone**.
|
|
Так как пространство имен проекта проецируется на префикс `local`, то все классы проекта можно использовать в форме `local:Название_Класса`. Так в данном случае в качестве содержимого кнопки устанавливается объект **Phone**.
|
|
|
|
|
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
|
|
|
|
|
-Для вывода содержимого любого объекта используется метод *ToString*. Этот метод объявлен в классе **Object** и по-умолчанию выводит просто название класса, в нашем случае **AvaloniaFirst.Phone**. Для того, чтобы получить нужную нам информацию об объекте необходимо переопределить метод *ToString*.
|
|
|
|
|
|
|
+Для вывода содержимого любого объекта используется метод *ToString*. Этот метод объявлен в классе **Object** и по-умолчанию выводит просто название класса. Для того, чтобы получить нужную нам информацию об объекте необходимо переопределить метод *ToString*.
|
|
|
|
|
|
|
|
Мы можем подключить любые другие пространства имен, классы которых мы хотим использовать в приложении. Например:
|
|
Мы можем подключить любые другие пространства имен, классы которых мы хотим использовать в приложении. Например:
|
|
|
|
|
|
|
@@ -803,10 +822,14 @@ xmlns:sys="clr-namespace:System;assembly=mscorlib"
|
|
|
|
|
|
|
|

|
|

|
|
|
|
|
|
|
|
-## Image. Ресурсы
|
|
|
|
|
|
|
+## Image
|
|
|
|
|
|
|
|
Для добавления ресурсов в проект можно создать в нём каталог (кликнуть правой кнопкой мышки на название проекта и выбрать *Добавить - Создать папку*) и скопировать в него нужный ресурс, в нашем случае картинку.
|
|
Для добавления ресурсов в проект можно создать в нём каталог (кликнуть правой кнопкой мышки на название проекта и выбрать *Добавить - Создать папку*) и скопировать в него нужный ресурс, в нашем случае картинку.
|
|
|
|
|
|
|
|
|
|
+>Обратите внимание, копировать нужно именно в интерфейсе Visual Studio, а не средствами ОС, иначе VS будет искать ресурс не в папке проекта, а в текущей папке VS.
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
И добавим картинку в сетку:
|
|
И добавим картинку в сетку:
|
|
|
|
|
|
|
|
```xml
|
|
```xml
|
|
@@ -815,35 +838,16 @@ xmlns:sys="clr-namespace:System;assembly=mscorlib"
|
|
|
<ColumnDefinition Width="100"/>
|
|
<ColumnDefinition Width="100"/>
|
|
|
<ColumnDefinition/>
|
|
<ColumnDefinition/>
|
|
|
</Grid.ColumnDefinitions>
|
|
</Grid.ColumnDefinitions>
|
|
|
- <StackPanel
|
|
|
|
|
- Orientation="Vertical"
|
|
|
|
|
- VerticalAlignment="Bottom"
|
|
|
|
|
- >
|
|
|
|
|
- <Image
|
|
|
|
|
- Source="img/latte-800x800.jpeg"/>
|
|
|
|
|
- </StackPanel>
|
|
|
|
|
-</Grid>
|
|
|
|
|
-```
|
|
|
|
|
-
|
|
|
|
|
-Если попытаться запустить проект, то Avalonia выдаст ошибку "Не найден ресурс".
|
|
|
|
|
-
|
|
|
|
|
-Для того, чтобы добавить картинку в ресурс есть два варианта:
|
|
|
|
|
-
|
|
|
|
|
-1. В контекстном меню файла картинки в дереве проекта выбрать пункт **Properties** и в поле **Build action** выбрать `AvaloniaResource`
|
|
|
|
|
-
|
|
|
|
|
-1. Если в проекте много картинок, то проще добавить весь каталог с картинками в ресурсы. Для этого в файл проекта (в режиме просмотра файловой системы открыть файл `<Название проекта>.csproj`) и в тег **ItemGroup** добавить запись
|
|
|
|
|
|
|
|
|
|
- ```xml
|
|
|
|
|
- <ItemGroup>
|
|
|
|
|
- <AvaloniaResource Include="img\**"/>
|
|
|
|
|
- </ItemGroup>
|
|
|
|
|
- ```
|
|
|
|
|
|
|
+ <Image
|
|
|
|
|
+ Source="img/latte-800x800.jpeg"/>
|
|
|
|
|
|
|
|
- 
|
|
|
|
|
|
|
+</Grid>
|
|
|
|
|
+```
|
|
|
|
|
|
|
|
-Атрибут **VerticalAlignment** устанавливает вертикальное выравнивание.
|
|
|
|
|
|
|
+Атрибут _VerticalAlignment_ устанавливает вертикальное выравнивание элемента относительно предка (Grid-а).
|
|
|
|
|
|
|
|
-Атрибут **Grid.ColumnSpan** (есть и **RowSpan**) позволяет разместить элемент не в одной ячейке Grid-a, а "размазать" на несколько. Например, можно сделать фоновую картинку (как в примере ниже) или горизонтальное меню в верхней строке.
|
|
|
|
|
|
|
+Атрибут _Grid.ColumnSpan_ (есть и _RowSpan_) позволяет разместить элемент не в одной ячейке Grid-a, а "размазать" на несколько. Например, можно сделать фоновую картинку (как в примере ниже) или горизонтальное меню в верхней строке.
|
|
|
|
|
|
|
|
```xml
|
|
```xml
|
|
|
<Image
|
|
<Image
|
|
@@ -858,9 +862,9 @@ xmlns:sys="clr-namespace:System;assembly=mscorlib"
|
|
|
|
|
|
|
|
Реализовать все примеры из лекции. В репозиторий добавить скриншоты результатов работы.
|
|
Реализовать все примеры из лекции. В репозиторий добавить скриншоты результатов работы.
|
|
|
|
|
|
|
|
-Напоминаю, что для добавления в **MarkDown** картинок используется синтаксис: ``
|
|
|
|
|
|
|
+Напоминаю, что для добавления в **MarkDown** картинок используется синтаксис: ``
|
|
|
|
|
|
|
|
-Использовать относительные пути и соблюдать регистр символов (у вас на Windows разницы не будет, но на сервере Linux и имена файлов регистрзависимые).
|
|
|
|
|
|
|
+Использовать относительные пути и соблюдать регистр символов (у вас на Windows разницы не будет, но на git-сервере Linux и имена файлов регистрзависимые).
|
|
|
|
|
|
|
|
Например:
|
|
Например:
|
|
|
|
|
|
|
@@ -870,6 +874,15 @@ xmlns:sys="clr-namespace:System;assembly=mscorlib"
|
|
|
|
|
|
|
|
---
|
|
---
|
|
|
|
|
|
|
|
|
|
+## Контрольные вопросы
|
|
|
|
|
+
|
|
|
|
|
+1. Технологии создания оконных приложений
|
|
|
|
|
+1. Особенности WPF
|
|
|
|
|
+1. Компоновка
|
|
|
|
|
+1. Grid
|
|
|
|
|
+1. StackPanel
|
|
|
|
|
+1. WrapPanel
|
|
|
|
|
+
|
|
|
Предыдущая лекция | | Следующая лекция
|
|
Предыдущая лекция | | Следующая лекция
|
|
|
:----------------:|:----------:|:----------------:
|
|
:----------------:|:----------:|:----------------:
|
|
|
[Библиотеки классов](./t7_dll.md) | [Содержание](../readme.md#тема-8-оконные-приложения) | [Ресурсы](./wpf_resource.md)
|
|
[Библиотеки классов](./t7_dll.md) | [Содержание](../readme.md#тема-8-оконные-приложения) | [Ресурсы](./wpf_resource.md)
|