При построении графического интерфейса пользователя с использованием XAML мы задействуем различные XAML-элементы, которые представляют собой декларацию объекта одного из типов C#. Например, в предыдущей части мы рассмотрели то, как в декларируется XAML-элемент Button
(кнопка) и как в дальнейшем мы можем использовать объект типа Button
в коде C#. В этой части мы подробнее рассмотрим работу с XAML-элементами в .NET MAUI.
Свойства XAML-элементов
Вернемся к нашему шаблонному приложению .NET MAUI и посмотрим на содержимое файла MainPage.xaml, а точнее на один из XAML-элементов — Label
(метка). В приложении он выглядит следующим образом:
<Label Text="Hello, World!" Style="{StaticResource Headline}" SemanticProperties.HeadingLevel="Level1" />
Здесь разработчики постарались показать самые различные возможности XAML по работе с так называемыми объектными элементами (Object Element), то есть XAML-элементами, которые декларируют некие объекты. У нашего XAML-элемента определены три атрибута — Text
, Style
и SemanticProperties.HeadingLevel
. Эти же самые атрибуты в C#-коде представляют собой свойства объекта. Чтобы убедиться в этом, попробуем получить доступ к XAML-элементу в коде C#, используя подход из предыдущей части.
Добавим нашей метке атрибут x:Name
:
<Label x:Name="MyLabel" Text="Hello, World!" Style="{StaticResource Headline}" SemanticProperties.HeadingLevel="Level1" />
Теперь перейдем в файл отделенного кода (MainPage.xaml.cs
) и изменим конструктор класса MainPage
следующим образом:
public MainPage() { InitializeComponent(); MyLabel.Text = "Привет, мир!"; }
Здесь мы уже привычным для нас способом — в коде C# изменяем значение свойства Text
объекта MyLabel
. Теперь запустим приложение и убедимся, что текст метки изменился:
Казалось бы, XAML-элемент
Label
— достаточно простой элемент. Однако, даже такой простой элемент управления содержит множество самых различных свойств, включая и свойства, которые представляют из себя сложные типы данных — объекты других классов. Если свойство представляет из себя простой тип — строку, число и т.д., то в XAML нам достаточно указать его значение. Например, свойство Text
— простое.
Если же свойство XAML-элемента представляет из себя объект другого типа, то прежде, чем задать значение этого свойства необходимо где-либо определить объект необходимого нам типа и только затем указать его в качестве значения свойства. Например, посмотрите как задается значение свойства Style
— стиль элемента
<Label Text="Hello, World!" Style="{StaticResource Headline}" SemanticProperties.HeadingLevel="Level1" />
Как работать со статическими ресурсами мы изучим далее, пока же нам необходимо разобраться с тем как задается значение свойства. Свойство Style
в C# объявлено следующим образом:
public class Style : System.Windows.Threading.DispatcherObject, System.Windows.Markup.IAddChild, System.Windows.Markup.INameScope, System.Windows.Markup.IQueryAmbient
это достаточно сложный класс, реализующий целый ряд интерфейсов. Чтобы объявить значение этого свойства у Label
мы должны каким-то образом декларировать такой объект в XAML или же создать его в коде C#. Посмотрим как стиль элемента объявляется в XAML. Для этого поставьте курсор мыши на строку Headline
, кликните правой кнопкой мыши и выберите в меню пункт «Перейти к определению»
В редакторе кода откроется файл Style.xaml на первой строке в которой объявляется стиль с ключом
Headline
:
<Style TargetType="Label" x:Key="Headline"> <Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource MidnightBlue}, Dark={StaticResource White}}" /> <Setter Property="FontSize" Value="32" /> <Setter Property="HorizontalOptions" Value="Center" /> <Setter Property="HorizontalTextAlignment" Value="Center" /> </Style>
Здесь задается цвет текста в зависимости от темы оформления, размер шрифта, а также выравнивание по горизонтали и вертикали. После того, как XAML-элемент объявлен он используется для задания стиля метки.
Содержимое XAML-элемента
Содержимое XAML-элемента, то есть то, что должен увидеть пользователь, может быть либо обычным текстом, лбо вложенным XAML-элементом. При этом, не совсем очевиден тот факт, что в XAML содержимое элемента может определяться разными и, зачастую, взаимозаменяемыми способами. Опять же, вернемся к нашем метке. Здесь продемонстрирован один из способов определения содержимого (текста) метки — с использованием атрибутов:
<Label Text="Hello, World!" Style="{StaticResource Headline}" SemanticProperties.HeadingLevel="Level1" />
Здесь свойство Text
определяет содержимое XAML-элемента. Второй способ выглядит следующим образом:
<Label Style="{StaticResource Headline}" SemanticProperties.HeadingLevel="Level1"> Привет, мир! </Label>
здесь содержимое расположено между открывающим и закрывающим тегом XAML-элемента. И, наконец, третий способ — использование в качестве содержимого объекта:
<Label Style="{StaticResource Headline}" SemanticProperties.HeadingLevel="Level1"> <Label.Text> Привет, мир </Label.Text> </Label>
Здесь текст метки располагается внутри вложенного элемента <Label.Text> — это т.н. синтаксис элемента свойства в XAML, то есть мы используем следующую форму тега <Имя_объекта.Свойство_объекта>
. Следует отметить, что в XAML для обозначения содержимого элемента могут использоваться различные имена параметров и вложенных объектов. Например, для метки содержимое определяется с использование Text
, для кнопки (Button
) — это будет Content
, для меню — Items
итак далее. Соответственно, в зависимости от того, какой XAML-элемент используется, мы можем применять один из способов определения содержимого. Так, для метки нам удобно использовать атрибут так как содержимым является обычный текст. Для меню может быть выгоднее использование третьего способа — с вложенным объектом так как меню может содержать несколько элементов, а каждый элемент может включать в себя текст, иконку, URI для перехода и так далее.
В XAML действует также ограничение — для XAML-элемента содержимое должно быть только одно. То есть вот так делать нельзя:
<Label Style="{StaticResource Headline}" SemanticProperties.HeadingLevel="Level1"> <Label.Text> Привет, мир </Label.Text> <Label.Text> Hello, world </Label.Text> </Label>
В Visual Studio вы увидите сообщение:
И хоть в данном случае приложение запуститься и метка будет содержать текст «Привет, мир», в более сложных ситуациях, когда вы определите несколько вариантов содержимого в одном элементе, вы можете столкнуться с такими проблемами как:
- Приложение не запускается даже в режиме отладки, выдавая исключение в момент запуска отладки
- Приложение запускается в режиме отладки, но в момент запуска, например, из Проводника Windows приложение закрывается без каких-либо сообщений об ошибке.
Предупредить эти ситуации, конечно, можно предварительно настроив компиляцию проекта, но всё же не стоит игнорировать такие предупреждение, как показано на рисунке выше.
Итого
Атрибуты в элементах XAML являются свойствами объектов C#. При этом, для XAML-элементов может определяться содержимое. Содержимое элемента может определяться несколькими способами, но оно (содержимое) может быть у элемента только одно.