Получить первоначальное представление о назначении и области применения языка XAML, составить представление о структуре XAML-документа, изучить основные синтаксические конструкции.
Построение пользовательских интерфейсов для WPF- и Silverlight-приложений осуществляется с применением языка расширенной разметки приложений XAML (Extensible Application Markup Language). XAML-документ содержит разметку, описывающую внешний вид и поведение окна или страницы приложения, а связанные с ним файлы кода C# - логику приложения. Язык XAML обеспечивает разделение процесса дизайна приложения (графической части) и разработки бизнес-логики (программного кода) между дизайнерами и разработчиками. WPF XAML является подмножеством языка XML и позволяет описывать WPF-содержимое таких элементов как векторная графика, элементы управления и документы.
XAML базируется на языке расширенной разметки XML (Extensible Markup Language) и его синтакс определяется следующими правилами [ 3 ] :
Язык XAML характеризуется самоописанием. Каждый элемент в XAML-документе представляет имя типа (такие как Button, Window или Page ) в рамках заданного пространства имен. Атрибуты элементов используются для задания свойств ( Name, Height, Width и т.п.) и событий ( Click, Load и т.д.) соответствующих объектов.
При создании WPF-приложения MyFirstWpfProject VisualStudio генерирует следующий XAML-документ.
<Window x:Class="MyFirstWpfProject.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <Grid> </Grid> </Window>
XAML-документ WPF-приложения MyFirstWpfProject начинается с дескриптора < Window...>. Все дескрипторы XAML-документа начинаются символами <, а завершаются символами >. Любой XAML-документ состоит из XAML-элементов. Каждый XAML-документ (XAML-элемент) начинается открывающимся дескриптором (например < Window >), за которым следует содержимое документа (например, текстовая строка или другие XAML-элементы). В открывающем дескрипторе могут присутствовать описания атрибутов (например, Class, xmlns, Title, Height, Width и др.). XAML-документ (XAML-элемент) должен завершаться закрывающимся дескриптором (например, /> или < /Window >). Текст XAML-документа должен содержать один корневой элемент – элемент верхнего уровня вложенности. В XAML-документе WPF-приложения MyFirstWpfProject таким элементом является < Window >. В корневой элемент могут быть добавлены другие XAML-элементы. В рассматриваемом XAML-документе это элемент < Grid >.
В процессе компиляции XAML-документа WPF-приложения синтаксический анализатор переводит XAML файлы в файлы языка двоичной разметки приложений BAML ( Binary Application Markup Language ), которые затем встраиваются в виде ресурсов в сборку проекта. Для построения классов WPF-приложения синтаксический анализатор использует пространство имен, которое определено в корневом дескрипторе XAML-документа.
Пространство имен в XAML-документе задается с помощью атрибута xmlns. В приведенном выше документе объявлено два базовых пространства имен:
Второе пространство имен используется для включения специфичных для XAML лексем – "ключевых слов" [ [ 9 ] ]. В табл.1.1 приведены наиболее часто используемые ключевые слова XAML.
В WPF-приложениях кроме базовых применяют специальные, необязательные пространства имен:
В атрибуты объекта Window могут быть добавлены следующие XAML-описания.
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="600"
Данное XAML-описание объявляет необязательные пространства имен с префиксами mc и d. Свойства DesignHeight и DesignWidth находятся в пространстве имен, помеченном префиксом d. Данные свойства определяют, что во время разработки проекта приложения в дизайнере Visual Studio окно должно иметь размеры 300x600. Свойство Ignorable находится в пространстве имен, помеченном префиксом mc, и информирует синтаксический анализатор о том, что он должен игнорировать часть XAML-документа, помеченные префиксом d.
В XAML-документе WPF-приложения часто возникает необходимость обеспечить доступ к каким-либо другим пространствам имен проекта. В этом случае необходимо определить новый префикс и задать пространство имен. Если в проекте имеется пространство имен MyFirstWpfProject.Commands, то подключение его к XAML-документу WPF-приложения будет иметь следующий вид (command – используется в качестве префикса).
xmlns:command="clr-namespace: MyFirstWpfProject.Commands"
Префикс (command) используется для ссылки на пространство имен в XAML-документе. Лексеме clr-namespace присваивается название пространства имен .NET в сборке.
Для описания класса в XAML-документе используется атрибут Class. Строка XAML-документа
<Window x:Class="MyFirstWpfProject.MainWindow" ...>
предписывает создать класс MyFirstWpfProject.MainWindow на базе класса Window. Префикс x атрибута Class определяет то, что данный атрибут помещается в пространство имен XAML. Класс MainWindow генерируется автоматически во время компиляции. Для части класса автоматически генерируется код (частичный (partial) класс):
namespace MyFirstWpfProject { /// <summary> /// Логика взаимодействия для MainWindow.xaml /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } } }
Когда выполняется компиляция приложения, XAML-файл, который определяет пользовательский интерфейс ( MainWindow.xaml ), транслируется в объявление типа CLR , которое объединяется с логикой приложения из файла класса отдельного кода ( MainWindow.xaml.cs ).
Метод InitializeComponent() генерируется во время компиляции приложения и в исходном коде не присутствует.
Для программного управления элементами управления, описанными в XAML-документе необходимо для элемента управления задать XAML атрибут Name. Так для задания имени элементу Grid необходимо записать следующую разметку:
<Grid Name="grid"> </Grid>
Простые свойства задаются в XAML-документе в соответствии со следующим синтаксисом:
ИмяСвойства ="значение"
Например, Name = "grid1"
При необходимости задать свойство, которое является полноценным объектом, используются сложные свойства в соответствии с синтаксисом "свойство-элемент":
Родитель.ИмяСвойства
Например, для контейнера StackPanel нам необходимо задать градиентную кисть для заливки панели, что определяется атрибутом Background. Это реализуется с помощью дескрипторов <StackPanel.Background> . . . </StackPanel.Background>.
Для задания значения свойства из выделенного класса используется расширение разметки, которое обеспечивает расширение грамматики XAML новой функциональностью. Расширения разметки могут использоваться во вложенных дескрипторах или в XAML-атрибутах. Когда это используется в атрибутах, то необходимо применять фигурные скобки {...}.
Расширения разметки используют следующий синтаксис:
{КлассРасширенияРазметки Аргумент }
Расширения разметки реализуются классами, дочерними от класса System.Windows.Markup.MarkupExtention. Базовый класс MarkupExtention имеет метод ProvideValue(), который предоставляет нужное значение для атрибута. Например, для задания атрибуту Foreground объекта Button статического свойства, определенного в другом классе, необходимо создать следующее XAML-описание.
<Button Foreground="{x:Static SystemColors.ActiveCaptionBrush}" />
При компиляции синтаксический анализатор создаст экземпляр класса Static Extention, затем вызовет метод ProvideValue(), который извлечет нужное значение и установит его для свойства Foreground.
Расширения разметки могут использоваться как вложенные свойства.
Присоединенные свойства описывают свойства, которые могут применяться к нескольким элементам управления, но которые определены в другом классе. В WPF-приложениях присоединенные свойства часто используются для управления компоновкой элементов интерфейса. Синтаксис присоединенных свойств следующий.
ОпределяющийТип.ИмяСвойства
Например, если необходимо расположить кнопку в нулевой строке сетки, то необходимо сделать следующее XAML-описание.
<Button . .. Grid.Row="0" > .... </Button>
Здесь присоединенным свойством является Grid.Row, то есть свойство Row элемента Grid, которое не является свойством объекта Button. Свойство Row присоединяется к свойствам объекта Button, поскольку данный объект располагается в контейнере Grid.
Атрибуты объектов могут использоваться для присоединения обработчиков событий, используя следующий синтаксис.
ИмяСобытия = "ИмяМетодаОбработчикаСобытия"
Например, для кнопки событию её нажатия Click можно установить обработчик события Exit_Click.
<Button Name="Exit" Content="Выход" Click="Exit_Click" />
Определяя в XAML-описании обработчик Exit_Click, необходимо в коде класса иметь метод с корректной сигнатурой. Ниже приведен код, который генерируется автоматически при создании описания обработчика события в XAML-описании.
private void Exit_Click(object sender, RoutedEventArgs e) { . . . . . }
Язык расширенной разметки приложений XAML, язык двоичной разметки приложений BAML, XAML-документ, XAML-элемент, корневой элемент XAML-документа, дескриптор, язык двоичной разметки приложений, синтаксический анализатор, базовое пространство имен XAML-документа, ключевые слова XAML, лексема clr-namespace, префикс в XAML-документе, простое свойство в XAML-документе, сложное свойство в XAML-документе, расширение разметки в XAML-документе, присоединенные свойства в XAML-документе, присоединение обработчиков событий в XAML-документе.
В данной теме были рассмотрены основные синтаксические конструкции языка XAML и приведены простые примеры их реализации. Проектирование WPF-приложений требует от разработчика понимания структуры и содержания XAML-документа, описывающего интерфейс создаваемой системы. В последующих темах курса будут рассматриваться различные аспекты построения WPF- и Silverlight-приложений и необходимым условием эффективной работы создателя таких систем является знание основ языка XAML.