Когда речь идёт про возможности языка C# или, например, про разработку приложений ASP.NET Core Web API, то всё, что нам необходимо для просмотра результатов работы приложения — консоль. В свою очередь, что касается .NET MAUI, то этот фреймворк всё же, в первую очередь, рассчитан на создание красивых приложение с графическим интерфейсом. Поэтому и мы начнем наше изучение .NET MAUI именно с построения графического интерфейса и основ декларативного языка XAML.
XAML
XAML (eXtensible Application Markup Language) — расширяемый язык разметки для приложений, основанный на XML. Язык разработан Microsoft для декларативного программирования приложений. На текущий момент XAML является фактически центральным звеном для таких технологий и платформ как WPF, UWP и, конечно же, .NET MAUI.
Несмотря на то, что XAML основан на XML, этот язык разметки принципиально отличается как от самого XML, так и от того же HTML, как минимум, тем, что XAML с помощью применяемых в нем объектов «привязан» к типам платформы .NET.
Одним из преимуществ использования XAML в проектах является то, что благодаря тому, что интерфейс приложения разрабатывается на XAML, а логика — на C#, появляется возможность разделить проект на две большие части:
- всё, что связано с графическим интерфейсом разрабатывается дизайнером.
- вся логика работы приложения ложится на плечи разработчика.
С одной стороны, это действительно так — мы имеем такую возможность. И выглядит это довольно заманчиво, на первый взгляд. Однако, не так уж и часто мы можем встретить внутри небольшой команды разработчиков отдельную штатную единицу профессионального дизайнера, который не только владеет инструментами для создания графики, но и знает язык XAML, а значит и владеет информацией о том, что из себя представляют типы данных .NET, как использовать события C# и т.д.. Поэтому, так или иначе, но разработчику проекта необходимо знать не только C#, но и прекрасно разбираться в том, как наиболее эффективно использовать возможности XAML.
Структура XAML-документа
Вернемся к нашему первому приложению .NET MAUI из предыдущей части. В этом приложении уже содержится три файла XAML с которым мы уже знакомы в самых общих чертах:
Для начала, откроем в редакторе файл
App.xaml
и посмотрим на его структуру:
<?xml version = "1.0" encoding = "UTF-8" ?> <Application xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:FirstApp" x:Class="FirstApp.App"> <Application.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="Resources/Styles/Colors.xaml" /> <ResourceDictionary Source="Resources/Styles/Styles.xaml" /> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </Application.Resources> </Application>
На первый взгляд, этот документ ничем не отличается от обычного XML-документа — здесь также прослеживается некоторая структура. Корневой элемент Application
содержит вложенные элементы, а также пространства имен и атрибут x:Class
. Аналогичным образом, но с другими корневыми элементами, выглядят и два других файла.
Так, AppShell.xaml
содержит в качестве корневого элемента Shell
:
<?xml version="1.0" encoding="UTF-8" ?> <Shell x:Class="FirstApp.AppShell" xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:FirstApp" Shell.FlyoutBehavior="Flyout" Title="FirstApp"> <ShellContent Title="Home" ContentTemplate="{DataTemplate local:MainPage}" Route="MainPage" /> </Shell>
Забегая немного вперед, отмечу, что Shell
представляет собой страницу-оболочку, которая призвана упростить создание графического интерфейса приложения. Как минимум, благодаря использованию Shell
мы получаем уже готовое к использованию боковое меню приложения.
В свою очередь MainPage.xaml представляет собой страницу с неким содержимым:
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="FirstApp.MainPage"> <ScrollView> <VerticalStackLayout Padding="30,0" Spacing="25"> <Image Source="dotnet_bot.png" HeightRequest="185" Aspect="AspectFit" SemanticProperties.Description="dot net bot in a hovercraft number nine" /> <Label Text="Hello, World!" Style="{StaticResource Headline}" SemanticProperties.HeadingLevel="Level1" /> <Label Text="Welcome to .NET Multi-platform App UI" Style="{StaticResource SubHeadline}" SemanticProperties.HeadingLevel="Level2" SemanticProperties.Description="Welcome to dot net Multi platform App U I" /> <Button x:Name="CounterBtn" Text="Click me" SemanticProperties.Hint="Counts the number of times you click" Clicked="OnCounterClicked" HorizontalOptions="Fill" /> </VerticalStackLayout> </ScrollView> </ContentPage>
Здесь уже в качестве корневого элемента выступает ContentPage
. Даже, если вы мало знакомы с XML, а XAML для нас пока ещё новый язык программирования, зная основные элементы управления, используемые, например, в том же ныне устаревшем .NET Framework, нетрудно догадаться, что на странице MainPage.xaml расположена картинка (элемент Image
), текстовая метка (Label
) и кнопка (Button
). Эти элементы мы можем использовать в XAML-разметке благодаря пространствам имен.
Пространства имен XAML
Подобно XML, в XAML определяются пространства имен — специальные атрибуты корневого элемента документа, имена которых начинаются со строки xmlns
. Пространства имен в XAML играют практически ту же роль, что и пространства имен, подключаемые в файлах C#. Благодаря подключенным тем или иным пространствам имен в документа XAML мы получаем возможность использовать объекты .NET. Так, например, посмотрим ещё раз на файл App.xaml. Здесь подключаются три пространства имен:
xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:FirstApp"
Первое пространство имен http://schemas.microsoft.com/dotnet/2021/maui содержит основные элементы для построения графического интерфейса приложения .NET MAUI. Например, те самые кнопки, метки, элементы для вывода картинок и так далее.
Пространство имен http://schemas.microsoft.com/winfx/2009/xaml определяется с помощью атрибута xmlns:x
. Здесь содержатся такие важные для использования XAML элементы как Name
, Key
, Class
и так далее. Это пространство имен объявляется с префиксом x
, что означает то, что все элементы из этого пространства имен должны начинаться с этого же префикса — x
. Так, например, чтобы использовать в разметке элемент x:Class="FirstApp.App"
здесь же после пространств имен используется с этим префиксом.
И, наконец, третье пространство имен clr-namespace:FirstApp. Здесь используется префикс local
. В принципе, префиксы, обычно, выбираются разработчиком достаточно произвольно. Здесь более важным является префикс в имени пространства — clr-namespace: который указывает на то, что подключается пространство имен CLR с именем FirstApp
то есть пространство имен C#, используемое по умолчанию в нашем проекте. Благодаря этому пространству имен мы можем в разметке XAML ссылаться на типы, определяемые в C#-коде нашего приложения. Также, используя пространства имен XAML мы можем подключать в проект пространства имен из других сборок. Например, вот такая запись:
xmlns:controls="clr-namespace:Controls;assembly=MyControlLibrary"
означает, что подключается пространство имен Controls
из сборки MyControlLibrary
.
Code-behind в XAML
Как можно видеть по представленному выше коду, в разметке XAML отсутствует какая-либо логика приложения — здесь содержится только описание интерфейса приложения и подключаются некие файлы ресурсов. Однако, XAML может содержать логику в виде так называемого code-behind и для этого используются частичные (разделяемые) классы C#. Обратите внимание на то, что с каждым XAML-файлом связан файл с именем, соответсвующим следующему шаблону [имя_файла_xaml].xaml.cs
.
В этих файлах и может содержаться логика приложения. Например, вернемся к нашему файлу App.xaml. Откроем также в редакторе кода связанный с этим файлом App.xaml.cs.
namespace FirstApp { public partial class App : Application { public App() { InitializeComponent(); } protected override Window CreateWindow(IActivationState? activationState) { return new Window(new AppShell()); } } }
и попробуем сопоставить разметку XAML с кодом C#:
Обратите внимание на то, что имя класса, определенного в XAML в атрибуте
x:Class
полностью соответствует имени класса, определенного в файле App.xaml.cs. Так,мы «связываем» класс C# с разметкой XAML. Точно таким же образом связываются классы C# с другими XAML-документами, например класс MainPage и MainPage.xaml. Благодаря такому подходу, мы можем ссылаться в XAML на поля и методы частичного класса. Эта возможность продемонстрирована как раз в MainPage.xaml. Обратите внимание на описание кнопки:
<Button x:Name="CounterBtn" Text="Click me" SemanticProperties.Hint="Counts the number of times you click" Clicked="OnCounterClicked" HorizontalOptions="Fill" />
Здесь x:Name — атрибут, действие которого подобно тому как мы объявляем переменную в коде C#. То есть здесь, используя привычные нам термины C#, мы объявляем переменную с именем CounterBtn
и типом Button
. Префикс x у атрибута говорит нам о том, что здесь мы задействовали пространство имен http://schemas.microsoft.com/winfx/2009/xaml.
Далее здесь же мы используем атрибут Clicked
, который представляет собой событие — клик по кнопке. В качестве значения для этого атрибута выступает имя метода OnCounterClicked
, который содержится в классе MainPage
(см. файл MainPage.xaml.cs):
namespace FirstApp { public partial class MainPage : ContentPage { int count = 0; public MainPage() { InitializeComponent(); } private void OnCounterClicked(object sender, EventArgs e) { count++; if (count == 1) CounterBtn.Text = $"Clicked {count} time"; else CounterBtn.Text = $"Clicked {count} times"; SemanticScreenReader.Announce(CounterBtn.Text); } } }
Обратите внимание на то, как мы можем ссылаться на объекты и методы C# в XAML (используя атрибут x:Class
в корневом элементе документа) и, наоборот — получать объект из разметки XAML (мы добавляем к элементу разметки атрибут x:Name
, чтобы сослаться на этот элемент в коде C#).
Итого
Итак, здесь мы рассмотрели самые основные моменты касающиеся языка XAML — из чего состоит документ XAML, для чего используются пространства имен и то, как мы можем связать разметку XAML м кодом C#. На этом наше изучение возможностей XAML не заканчивается и в следующих частях мы будем рассматривать возможности XAML более подробно.