Стандарт XAML достаточно очевиден, если понять несколько его основополагающих правил:
Каждый элемент в документе XAML отображается на экземпляр класса .NET. Имя элемента в точности соответствует имени класса. Например, элемент <Button> сообщает WPF, что должен быть создан объект Button.
Как и любой XML-документ, код XAML допускает вложение одного элемента внутрь другого. Как будет показано, XAML предоставляет каждому классу гибкость в принятии решения относительно того, как справиться с такой ситуацией. Однако вложение обычно является способом выразить включение (containment). Другими словами, если вы видите элемент Button внутри элемента Grid, то пользовательский интерфейс, возможно, включает Grid, содержащий внутри себя Button.
Свойства каждого класса можно устанавливать через атрибуты. Тем не менее, в некоторых ситуациях атрибуты не достаточно мощны, чтобы справиться с этой работой. В этих случаях понадобятся вложенные дескрипторы со специальным синтаксисом.
Хотя инструменты могут генерировать приемлемый код XAML, все же важно понимать основы синтаксиса XAML и то, как разметка в конечном итоге трансформируется в корректную сборку .NET. Взгляните на следующий простейший документ XAML, представляющий новое пустое окно (как оно создано в Visual Studio):
<Window x:Class="WpfApplication1.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>
Прежде всего, обратите внимание, что корневой элемент <Window> использует атрибут Class для указания имени класса, который будет сгенерирован при обработке этого файла XAML. Кроме того, атрибут Class снабжен префиксом х:. Заглянув в открывающий элемент <Window>, вы увидите, что этому префиксу дескриптора XML присваивается строка "http://schemas.microsoft.com/winfx/2006/xaml" для построения объявления пространства имен XML. Имейте в виду, что всякий раз, когда хотите сослаться на элемент, определенный в пространстве имен XAML http://schemas.microsoft.com/winfx/2006/xaml, вы должны указывать префикс - лексему х:.
В контексте открывающего дескриптора <Window> заданы значения для атрибутов Title, Height и Width, которые напрямую отображаются на одноименные свойства, поддерживаемые типом System.Windows.Window из сборки PresentationFramework.dll.
Ясно, что не достаточно просто указать имя класса. Анализатору XAML также нужно знать пространство имен .NET, где находится этот класс. Например, класс Window может существовать в нескольких пространствах имен - он может ссылаться на класс System.Windows.Window, на класс в компоненте от независимого разработчика или же на класс, определенный в вашем приложении. Чтобы определить, какой именно класс нужен на самом деле, анализатор XAML проверяет пространство имен XML, к которому относится элемент.
Вот как это работает. В примере документа, показанном ранее, определено два пространства имен:
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Пространства имен объявляются с помощью атрибутов. Эти атрибуты могут помещаться внутрь начального дескриптора любого элемента. Однако согласно принятым соглашениям все пространства имен, которые нужно использовать в документе, должны быть объявлены в самом первом дескрипторе, как это сделано в данном примере. Как только пространство имен объявлено, оно может использоваться в любом месте документа.
xmlns - это специализированный атрибут в мире XML, который зарезервирован для объявления пространств имен. В показанном выше фрагменте кода разметки объявлены два пространства имен, которые будут присутствовать в каждом создаваемом документе WPF XAML.
Основное пространство имен WPF. Оно охватывает все классы WPF, включая элементы управления, которые применяются для построения пользовательских интерфейсов (System.Windows, System.Windows.Controls, System.Windows.Data, System.Windows.Ink, System.Windows.Media, System.Windows.Navigation). В рассматриваемом примере это пространство имен объявлено без префикса пространства имен, поэтому становится пространством имен по умолчанию для всего документа. Другими словами, каждый элемент автоматически помещается в это пространство имен, если только не указано иное.
Пространство имен XAML. Оно включает различные служебные свойства XAML, которые позволяют влиять на то, как интерпретируется документ. Данное пространство имен отображается на префикс х. Это значит, что его можно применять, помещая префикс пространства имен перед именем элемента (как в <х:ИмяЭлемента>).
Как видите, пространство имен XML не соответствует какому-либо конкретному пространству имен .NET. Существует несколько причин, по которым создатели XML выбрали такое проектное решение. По существующему соглашению пространства имен XML часто имеют форму URI (как и в данном примере). Эти URI выглядят так, будто указывают на некоторое место в Интернете, хотя на самом деле это не так. Формат URI используется потому, что он делает маловероятным ситуацию, когда разные организации непреднамеренно создадут разные языки на базе XML с одинаковым пространством имен. Поскольку домен schemas.microsoft.com принадлежит Microsoft, только Microsoft использует его в названии пространства имен XML.
Другая причина отсутствия отображения "один к одному" между пространствами имен XML, используемыми в XAML, и пространствами имен .NET заключается в том, что это могло бы значительно усложнить документы XAML. Проблема в том, что WPF содержит свыше десятка пространств имен (все начинаются с System.Windows). Если бы каждое пространство имен .NET отображалось на отдельное пространство имен XML, пришлось бы указывать корректное пространство имен для каждого используемого элемента управления, что быстро привело бы к путанице. Вместо этого создатели WPF предпочли скомбинировать все эти пространства имен .NET в единое пространство имен XML. Это работает, потому что внутри разных пространств имен .NET, образующих часть WPF, нет классов с одинаковыми именами.
Информация пространства имен позволяет анализатору XAML находить правильный класс. Например, когда он просматривает элементы Window и Grid, то видит, что они помещены в пространство имен WPF по умолчанию. Затем он ищет соответствующие пространства имен .NET- до тех пор, пока не находит System.Windows.Window и System.Windows.Controls.Grid.
В дополнение к этим двум необходимым объявлениям пространств имен XML можно, а иногда и необходимо, определить дополнительные префиксы дескрипторов в открывающем элементе XAML-документа. Обычно это делается, когда нужно описать в XAML класс .NET, определенный во внешней сборке. Например, предположим, что вы построили несколько специальных элементов управления WPF и упаковали их в библиотеку под названием MyControls.dll.
Теперь, если необходимо создать новый экземпляр Window, который использует эти элементы, можно установить специальное пространство имен XML, отображаемое на библиотеку MyControls.dll, с использованием лексем clr-namespace и assembly.
Ниже приведен пример разметки, создающей префикс дескриптора, который может применяться для доступа к членам этой библиотеки:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:myDll="clr-namespace:MyControls;assembly=MyControls"
Title="MainWindow" Height="350" Width="525">
<Grid>
<myDll:MySomeControls />
</Grid>
</Window>
Лексеме clr-namespace присваивается название пространства имен .NET в сборке, в то время как лексема assembly устанавливается в дружественное имя внешней сборки *.dll. Такой синтаксис можно использовать для любой внешней библиотеки .NET, которой необходимо манипулировать внутри разметки.