До сих пор демонстрировалось создание базового интерфейса в XAML с использованием классов, являющихся частью WPF. Однако XAML задуман как средство общего назначения для создания экземпляров объектов .NET, включая те, что находятся в пространствах имен, не относящихся к WPF, и те, которые вы создаете сами. Рассмотрение создания объектов, которые не предназначены для экранного отображения в окне XAML, может показаться странным, но существует немало ситуаций, когда это оправдано. Примером может служить случай, когда вы используете привязку данных и хотите нарисовать информацию из другого объекта, чтобы отобразить ее в элементе управления. Другой пример - когда требуется установить свойство объекта WPF с применением объекта, не относящегося к WPF.
Например, WPF-элемент ListBox можно заполнить объектами данных. ListBox будет вызывать метод ToString(), чтобы получить текст для отображения каждого элемента в списке. (Для более качественного отображения списка можно создать шаблон данных, который извлечет множество фрагментов информации и сформатирует их соответствующим образом.)
Для того чтобы использовать класс, который не определен ни в одном из пространств имен WPF, понадобится отобразить пространство имен .NET на пространство имен XML. В XAML для этого предусмотрен специальный синтаксис:
xmlns:Префикс = "clr-namespace: ПространствоИмен; assembly=ИмяСборки"
Обычно это отображение пространства имен помещается в корневой элемент документа XAML - сразу после атрибутов, которые описывают пространства имен WPF и XAML. Эти части должны быть заполнены соответствующей информацией, как описано ниже:
Префикс XML, который будет использоваться для указания пространства имен в разметке XAML. Например, язык XAML использует префикс х.
Полностью квалифицированное название пространства имен .NET.
Сборка, в которой объявлен тип, без расширения .dll. Проект должен ссылаться на эту сборку. Если используется сборка вашего проекта, этот параметр можно опустить.
Например, ниже показано, как получить доступ к базовым типам пространства имен System и отобразить их на префикс sys:
xmlns:sys="clr-namespace:System;assembly=mscorlib"
Помните, что можно использовать произвольный префикс пространства имен до тех пор, пока он согласован по всему документу XAML. Однако префиксы sys и local обычно применяются при импорте пространства имен System и пространства имен для текущего проекта.
В идеале каждый класс, который должен использоваться в XAML, будет иметь конструктор без аргументов. Если это так, то анализатор XAML сможет создавать соответствующий объект, устанавливать его свойства и присоединять любые обработчики событий, которые вы укажете. XAML не поддерживает параметризованных конструкторов, и все элементы в WPF включают конструкторы без аргументов. Вдобавок необходимо иметь возможность устанавливать все желаемые детали, используя общедоступные свойства.
XAML не позволяет устанавливать общедоступные свойства или вызывать методы. Если класс, который планируется использовать, не имеет конструктора без аргументов, возможности некоторым образом ограничены. Если вы попытаетесь создать простой примитив (вроде строки, даты или числового типа), то сможете применить строковое представление данных в качестве содержимого внутри дескриптора. Анализатор XAML затем использует конвертер типа для преобразования этой строки в соответствующий объект. Ниже показан пример:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
Title="MainWindow" Height="350" Width="525">
<ListBox>
<ListBoxItem>
<sys:DateTime>11/04/2011</sys:DateTime>
</ListBoxItem>
<ListBoxItem>
<sys:DateTime>11/07/2011</sys:DateTime>
</ListBoxItem>
<ListBoxItem>
<sys:DateTime>10/31/2011</sys:DateTime>
</ListBoxItem>
</ListBox>
</Window>
Это работает, потому что класс DateTime применяет атрибут TypeConverter для привязки себя к DateTimeConverter. Конвертер DateTimeConverter распознает эту строку как корректный объект DateTime и преобразует его. При использовании этой техники нельзя применять атрибуты для установки любых свойств объекта. Если требуется создать класс, не имеющий конструктора без аргументов, и нет подходящего конвертера типов, которым можно было бы воспользоваться, значит, вам не повезло.
Некоторые разработчики преодолевают эти ограничения, создавая специальные классы-оболочки. Например, класс FileStream не включает конструктора без аргументов. Однако можно создать класс-оболочку, который его имеет. Этот класс-оболочка должен будет создать нужный объект FileStream в своем конструкторе, извлечь необходимую информацию и затем закрыть FileStream. Подобное решение не идеально, поскольку предполагает жесткое кодирование информации для конструктора класса, что усложняет обработку исключений. В большинстве случаев лучше будет манипулировать объектом с помощью небольшого кода обработки событий и полностью исключить его из XAML-разметки.