Общие сведения о XAML
Обновлен: Ноябрь 2007
В этом разделе описаны возможности языка Язык XAML (Extensible Application Markup Language) и показано, как можно использовать XAML для написания приложений Windows Presentation Foundation (WPF). В этом разделе описывается реализация XAML в Windows Presentation Foundation (WPF). Сам по себе XAML — это большее языковое понятие, чем Windows Presentation Foundation (WPF).
В этом разделе содержатся следующие подразделы.
- Декларативный язык с поддержкой управления потоком
- Объектные элементы XAML
- Задание свойств
- Ссылочные значения и расширения разметки
- Значения атрибутов с возможным преобразованием типов
- Типы коллекции и свойства коллекции XAML
- Свойства содержимого XAML
- Чувствительность к регистру и пробелам в XAML
- Дополнительные сведения о синтаксисе XAML
- Корневые элементы XAML и пространства имен XML
- События и код программной части XAML
- x:Name
- Вложенные свойства и события
- Базовые классы и XAML
- Безопасность в XAML
- Загрузка XAML из кода
- Что дальше?
- Связанные разделы
Декларативный язык с поддержкой управления потоком
XAML упрощает создание Пользовательский интерфейс для модели программирования .NET Framework. Можно создать элементы Пользовательский интерфейс в декларативной разметке XAML, а затем отделить определение Пользовательский интерфейс от логики времени выполнения, используя файлы с выделенным кодом, присоединенные к разметке с помощью определений разделяемых классов. Возможность перемежать код и разметку в XAML важна, поскольку XML сам по себе является декларативным и реально не предлагает модель для управления размещением. Основанный на XML декларативный язык интуитивно понятен для создания интерфейсов в диапазоне от прототипа до производства, особенно для людей с опытом веб-разработки и работы с веб-технологиями. В отличие от большинства других языков разметки, XAML непосредственно представляет создание экземпляров управляемых объектов. Этот общий принцип проектирования ведет к упрощению кода и доступа отладки для объектов, создаваемых в XAML.
Файлы XAML — это файлы XML, как правило, имеющие расширение .xaml.
В следующем примере XAML показано, сколь малое количество разметки необходимо для создания кнопки как части Пользовательский интерфейс. У созданной кнопки стилями темы задано визуальное представление по умолчанию, структурой класса задано поведение по умолчанию.
<StackPanel>
<Button Content="Click Me"/>
</StackPanel>
Объектные элементы XAML
У XAML есть набор правил, сопоставляющих объектные элементы с классами или структурами, атрибуты со свойствами или событиями, пространства имен XML с пространствами имен CLR. Элементы XAML сопоставлены с типами Microsoft .NET, как определено в используемых сборках, а атрибуты сопоставлены с членами этих типов.
В предыдущем примере заданы два объектных элемента: <StackPanel> (с закрывающим тегом) и <Button/> (который также имеет несколько атрибутов; атрибуты описаны далее). Строки StackPanel и Button сопоставлены с именами классов, определенных WPF и являющихся частью сборки WPF. При задании тега объектного элемента создается инструкция обработки XAML для создания нового экземпляра названного класса при загрузке страницы XAML. Каждый экземпляр класса создается путем вызова конструктора базового класса или структуры по умолчанию и дальнейшего сохранения результата. Чтобы быть полезными для работы в качестве объектного элемента в XAML, класс или структура должны предоставлять открытый конструктор по умолчанию (без параметров).
Задание свойств
Свойства в XAML задаются путем задания свойств объектного элемента с использованием различных возможностей синтаксиса. Какой именно синтаксис может быть использован для данного свойства, определяется в зависимости от характеристик задаваемого свойства.
При задании значений свойств добавляются возможности или характеристики объектных элементов. Начальное состояние основного экземпляра объекта для объектного элемента основано на поведении конструктора по умолчанию. Как правило, приложение будет использовать экземпляр, отличный от заданного полностью по умолчанию экземпляра любого объекта.
Синтаксис атрибута
В XAML свойства часто могут быть заданы как атрибуты. Синтаксис атрибутов — это наиболее рациональный синтаксис задания свойств, интуитивно понятный разработчикам, использовавшим языки разметки ранее. Например, следующая разметка создает кнопку с красным тестом и синим фоном, а также отображает текст, заданный в качестве Content.
<Button Background="Blue" Foreground="Red" Content="This is a button"/>
Синтаксис элемента свойства
Для некоторых свойств объектного элемента невозможен синтаксис атрибутов, так как объект или сведения, необходимые для задания значения свойства, не могут быть адекватно представлены в виде простой строки. В этих случаях может использоваться другой синтаксис — синтаксис элементов свойств. Синтаксис элементов свойств задает указанное свойство содержащего его элемента содержимым тега. Как правило, содержимое представляет собой объект типа, который свойство принимает в качестве значения (с задающим значение экземпляром, обычно заданным как другой объектный элемент). Синтаксис для элемента свойства сам по себе: <TypeName.Property>. После указания содержимого необходимо закрыть элемент свойства закрывающим тегом так же, как любой другой элемент (с помощью синтаксиса </TypeName.Property>). Для свойств, поддерживающих и синтаксис атрибутов, и синтаксис элементов свойств, оба синтаксиса производят одинаковый эффект, хотя некоторые детали, такие как обработка пустого пространства, могут немного различаться в зависимости от синтаксиса. Если допустим синтаксис атрибутов, его использование, как правило, более удобно и приводит к созданию более компактной разметки, но дело в стиле, а не в технических ограничениях. В следующем примере те же свойства задаются так же, как в предыдущем примере синтаксиса атрибутов, но на этот раз с помощью синтаксиса элементов свойств для всех свойств Button.
<Button>
<Button.Background>
<SolidColorBrush Color="Blue"/>
</Button.Background>
<Button.Foreground>
<SolidColorBrush Color="Red"/>
</Button.Foreground>
<Button.Content>
This is a button
</Button.Content>
</Button>
Синтаксис элементов свойств для XAML значительно отличается от основной интерпретации разметки XML. Для XML <TypeName.Property> представляет другой элемент, не обязательно предполагающий отношение себя как дочернего элемента и TypeName как родительского элемента. В XAML <TypeName.Property> непосредственно подразумевает, что Property является свойством TypeName, устанавливаемым по содержимому элемента свойства; это не может быть один элемент с названием, содержащим точку.
Свойства и наследование классов
Свойства, отображающиеся как XAML атрибуты элемента WPF, часто наследуются от базовых классов. Например, в предыдущем примере свойство Background не является немедленно объявленным свойством класса Button, если просмотреть определение класса, результаты отражения или документацию. Вместо этого класс Background наследуется от базового класса Control.
Поведение наследования классов для элементов WPF XAML является еще одним существенным отличием от основной интерпретации разметки XML. Наследование классов (в частности, когда промежуточные базовые классы являются абстрактными) является одной из причин того, что набор элементов XAML и их допустимых атрибутов очень сложно точно и полно представить с помощью типов схемы, которые обычно используются для программирования XML, таких как форматы DTD или XSD. Кроме того, "X" в XAML означает "extensible", то есть расширяемый, а расширяемость устраняет необходимость полноты любого данного представления того, "чем является XAML для WPF" (хотя эту проблему можно решить путем сохранения отдельных определений пространства имен XML; эта концепция обсуждается ниже).
Ссылочные значения и расширения разметки
Расширения разметки являются понятием XAML. В синтаксисе атрибутов фигурные скобки ({и}) указывают на использование расширения разметки. При XAML-обработке расширения разметки обрабатываются иначе, чем значения атрибутов, обычно рассматриваемые как строковые литералы или непосредственно как строки, которые могут быть преобразованы в тип String.
Когда свойства принимают значения ссылочного типа, эти свойства часто требуют либо синтаксиса элементов свойств (который всегда создает новый экземпляр), либо ссылки на объект с помощью расширения разметки. Расширение разметки может потенциально возвращать существующий экземпляр и, таким образом, может быть более гибким или может привести к сокращению издержек объекта.
Когда расширение разметки используется для представления значения атрибута, значение атрибута должно быть взамен предоставлено логикой в дополнительном классе для соответствующего расширения разметки. Наиболее распространенными расширениями разметки, используемыми при программировании приложений WPF, являются Binding, используемое для сохранения выражений привязки данных, и ссылки на ресурсы StaticResource и DynamicResource. С помощью расширений разметки можно использовать синтаксис атрибутов для присвоения свойствам ссылочных значений, даже если это свойство не поддерживает синтаксис атрибутов для прямого создания экземпляров объекта, а также можно обеспечить специфическое поведение, откладывающее общее поведение для требования, что XAML свойства должны быть заполнены значениями типа свойства.
Например, в следующем примере значение свойства Style задается с помощью синтаксиса атрибутов. Свойство Style принимает экземпляр класса Style, ссылочный тип, который по умолчанию не может быть указан при использовании синтаксиса атрибутов. Но в этом случае атрибут ссылается на определенное расширение разметки, StaticResource. Когда это расширение разметки обрабатывается, оно возвращает ссылку на стиль, экземпляр которого был ранее создан в качестве ключевого ресурса в словаре ресурсов.
<Page.Resources>
<SolidColorBrush x:Key="MyBrush" Color="Gold"/>
<Style TargetType="Border" x:Key="PageBackground">
<Setter Property="Background" Value="Blue"/>
</Style>
...
</Page.Resources>
<StackPanel>
<Border Style="{StaticResource PageBackground}">
...
</Border>
</StackPanel>
Ресурсы представляют собой только одно применение расширений разметки, доступное в WPF или XAML. Список ссылок на расширения разметки см. в разделе Пространство имен WPF расширения XAML или Возможности пространства имен языка XAML (x:). Дополнительные сведения о расширениях разметки содержатся в разделе Расширения разметки и XAML.
Значения атрибутов с возможным преобразованием типов
В разделе "Синтаксис атрибутов" было отмечено, что должна быть возможность задать значение атрибута строкой. Основная, исходная обработка преобразования строк в другие типы объектов или простые значения основана на самом типе String. Но многие типы WPF или члены этих типов расширяют основное поведение обработки атрибутов таким образом, что экземпляры более сложных типов объектов могут быть заданы как значения атрибутов через строку. На уровне кода эта обработка осуществляется путем указания преобразователя типов CLR, который обрабатывает строковое значение атрибута. Структурный тип Thickness, обычно используемый для указания размера прямоугольной области, например, Margin, является примером типа, для которого специальный синтаксис атрибутов с возможным преобразованием типов доступен всем свойствам, принимающим такой тип, в целях обеспечения удобства использования в разметке XAML. В следующем примере синтаксис атрибутов с возможным преобразованием типов используется для присвоения значения Margin:
<Button Margin="10,20,10,30" Content="Click me"/>
Предыдущий пример синтаксиса атрибутов эквивалентен следующему более подробному примеру синтаксиса, где Margin устанавливается через синтаксис элементов свойств, содержащий объектный элемент Thickness, и четыре ключевых свойства Thickness задаются как атрибуты нового экземпляра:
<Button Content="Click me">
<Button.Margin>
<Thickness Left="10" Top="20" Right="10" Bottom="30"/>
</Button.Margin>
</Button>
Следует ли использовать синтаксис с возможным преобразованием типов или более подробный эквивалентный синтаксис, обычно зависит от стиля написания кода, но синтаксис с возможным преобразованием типов способствует созданию более рациональной разметки. (Однако существует ряд объектов, для которых преобразование типов является единственным способом присвоения свойству значения нужного типа, так как для самого объектного типа отсутствует конструктор по умолчанию. Например, Cursor.)
Дополнительные сведения о поддержке синтаксиса атрибутов с возможным преобразованием типов см. в разделе TypeConverters и XAML.
Типы коллекции и свойства коллекции XAML
XAML указывает языковое средство, с помощью которого объектный элемент, представляющий тип коллекции, может быть намеренно опущен в разметке. При обработке обработчиком XAML свойства, принимающего тип коллекции, экземпляр соответствующего типа коллекции создается неявно, даже в том случае, когда объектный элемент для этой коллекции не присутствует в разметке. В ссылочных страницах Пакет SDK для типов коллекции этот синтаксис с намеренным опущением объектного элемента для коллекции иногда отмечен в разделах синтаксиса XAML как синтаксис неявных коллекций.
Синтаксис неявных коллекций доступен для типов, которые реализуют IList или IDictionary, или для массивов.
Ранее был приведен пример неявного синтаксиса коллекции без явного его вызова, в примере ресурсов XAML:
<Page.Resources>
<SolidColorBrush x:Key="MyBrush" Color="Gold"/>
<Style TargetType="Border" x:Key="PageBackground">
<Setter Property="Background" Value="Blue"/>
</Style>
...
</Page.Resources>
<StackPanel>
<Border Style="{StaticResource PageBackground}">
...
</Border>
</StackPanel>
За исключением корневого элемента, каждый объектный элемент на странице, вложенный как дочерний элемент другого элемента, является элементом одного или обоих следующих классов: член неявного свойства коллекции для родительского элемента или элемент, указывающий значение свойства содержимого XAML для родительского элемента (свойства содержимого XAML будут рассмотрены далее). Другими словами, связь родительских и дочерних элементов на странице разметки является одним объектом в корне, и каждый объектный элемент ниже корня является одним экземпляром, предоставляющим значение свойства родительского элемента, или одним из элементов в коллекции, также являющейся значением свойства типа коллекции для родительского элемента. В примере использования ресурсов, свойство Resources принимает объект типа ResourceDictionary. Следующий пример является эквивалентный синтаксисом с явно заданным объектным элементом для ResourceDictionary.
<Page.Resources>
<ResourceDictionary>
<SolidColorBrush x:Key="MyBrush" Color="Gold"/>
<Style TargetType="Border" x:Key="PageBackground">
<Setter Property="Background" Value="Blue"/>
</Style>
...
</ResourceDictionary>
</Page.Resources>
<StackPanel>
<Border Style="{StaticResource PageBackground}">
...
</Border>
</StackPanel>
</Page>
Коллекция Resources является примером свойства коллекции, которое присутствует во многих общих элементах уровня среды WPF. Для задания этого свойства в XAML требуется синтаксис элементов свойств. Каждый объектный элемент внутри элемента свойства становится элементом коллекции (реализация IDictionary). Хотя у самого типа коллекции обычно есть свойство или индексатор, содержащий элементы, это свойство не может быть задано в разметке; он полностью неявное. Для ResourceDictionary этим свойством является индексатор Item.
Более полный пример использования словаря ресурсов см. в разделе Практическое руководство. Определение и создание ссылки на ресурс.
Свойства содержимого XAML
XAML определяет языковое средство, с помощью которого любой класс, который может быть использован в качестве объектного элемента XAML, может назначить только одно из его свойств свойством содержимого XAML для экземпляров класса. При обработке обработчиком XAML объектного элемента, имеющего свойство содержимого XAML, любые дочерние элементы XML этого объектного элемента обрабатываются так, как если бы они содержались в неявном теге элемента свойства, представляющем это свойство содержимого. В разметке синтаксис элементов свойств для свойства содержимого XAML может быть опущен. Все дочерние элементы, заданные в разметке, станут значением свойства содержимого XAML.
В самом первом примере в этом разделе уже было показано использование контекстного свойства XAML без его вызова.
<StackPanel>
<Button Content="Click Me"/>
</StackPanel>
Здесь Button является дочерним элементом StackPanel. Это рациональная и интуитивно понятная разметка, в которой опущены два тега по двум разным причинам.
Опущен элемент свойства StackPanel.Children: StackPanel является производным от Panel. Panel, определяет Panel.Children как его свойство содержимого XAML. Все классы, производные от Panel, таким образом имеют свойство содержимого XAML, и элемент свойства для Panel.Children может быть опущен.
Опущен объектный элемент UIElementCollection: свойство Panel.Children принимает тип UIElementCollection, реализующий IList. Таким образом, тег объектного элемента UIElementCollection может быть опущен на основании определенных правил XAML для коллекций. В этом случае UIElementCollection фактически не может быть создан как объектный элемент. Даже нет возможности явного объявления этого объекта коллекции. Это происходит потому, что UIElementCollection не предоставляет конструктор по умолчанию. Некоторые другие типы коллекции WPF также не предоставляют конструкторов для использования объектных элементов, поскольку обработка синтаксиса коллекции XAML по-прежнему позволяет им работать в XAML неявно. Вот почему объектный элемент UIElementCollection закомментирован в примере; если убрать комментарии, пример не будет скомпилирован.
<StackPanel>
<StackPanel.Children>
<!--<UIElementCollection>-->
<Button>
<Button.Content>
Click Me
</Button.Content>
</Button>
<!--</UIElementCollection>-->
</StackPanel.Children>
</StackPanel>
Внутренний текст и свойства содержимого XAML
Существует другой вариант примера StackPanel / Button.
<StackPanel>
<Button>Click Me</Button>
</StackPanel>
Следует обратить внимание на изменения в способе задания отображаемого текста для Button. Свойство Content было задано в синтаксисе атрибута ранее; в этом случае отображаемая строка является внутренним текстом в объектном элементе Button. Этот синтаксис работает, поскольку Content является свойством содержимого XAML базового для Button класса ContentControl. Строка в элементе вычисляется на основании типа свойства для свойства Content, являющегося Object. Object не будет пытаться произвести какое-либо преобразование строкового типа, таким образом, значение свойства Content становится значением символьной строки. Также содержимое в элементе управления Button может быть любым одиночным объектом Object. Такие элементы управления, как Button, обычно определяют свойство содержимого XAML, чтобы такой класс, как свойство содержимого XAML, мог использоваться для пользовательского интерфейса и отображения текста, для композиции элементов управления или для обеих целей.
Возможность поместить строки внутрь элемента как содержимое, чтобы создать разметку, схожую с другими общими языками разметки, особенно важна для поточной модели документа (дополнительные сведения см. в разделе Документы в Windows Presentation Foundation) и для локализации (см. раздел Глобализация и Windows Presentation Foundation).
Значения свойств содержимого XAML должны быть непрерывными
Значение свойства содержимого XAML должно быть задано либо целиком до, либо целиком после любых других элементов свойств данного объектного элемента. Это не зависит от того, задано ли значение свойства содержимого XAML в виде строки или в виде одного или нескольких объектов. Например, следующая разметка не компилируется:
<Button>I am a
<Button.Background>Blue</Button.Background>
blue button</Button>
Это неверно, поскольку если бы этот синтаксис был явным с использованием синтаксиса элементов свойств для свойства содержимого, то свойство содержимого было бы задано дважды:
<Button>
<Button.Content>I am a </Button.Content>
<Button.Background>Blue</Button.Background>
<Button.Content> blue button</Button.Content>
</Button>
Аналогично неверным примером является случай, когда свойство содержимого представляет собой коллекцию, и дочерние элементы перемежаются элементами свойств:
<StackPanel>
<Button>This example</Button>
<StackPanel.Resources>
<SolidColorBrush x:Key="BlueBrush" Color="Blue"/>
</StackPanel.Resources>
<Button>... is illegal XAML</Button>
</StackPanel>
Модели содержимого
Класс может поддерживать использование в качестве элемента XAML в терминах синтаксиса, но этот элемент будет работать должным образом в приложении или на странице только при его помещении в ожидаемое положение в общей модели содержимого или в дереве элементов. Например, MenuItem обычно может быть помещен только в качестве дочернего элемента класса, производного от MenuBase, например, Menu. Модели содержимого для определенных элементов описаны в документации как часть примечаний на страницах класса для элементов управления и других классов, которые могут использоваться в качестве элементов WPF XAML. Более сложные модели содержимого, использующиеся в некоторых элементах управления, описаны в документации в отдельном разделе. См. раздел Модели содержимого.
Чувствительность к регистру и пробелам в XAML
XAML учитывает регистр. Объектные элементы, элементы свойств и имена атрибутов должны быть заданы с помощью соответствующего регистра при сравнении по имени с базовым типом в сборке или с членом типа. Значения для атрибутов не всегда чувствительны к регистру. Учет регистра для значений будет зависеть от типа преобразователя поведения, связанного со свойством, которое принимает значение, или с соответствующим типом значения свойства. Например, свойства, которые принимают тип Boolean, могут принимать значение true или True как эквивалентные значения, но только потому, что преобразователь строкового формата по умолчанию для Boolean уже рассматривает их как эквиваленты.
Обработчики XAML и сериализаторы будут игнорировать или удалять все незначимые пробелы, а также выполнять нормализацию всех значимых пробелов. Данное поведение типично только при задании строки в свойствах содержимого XAML. Проще говоря, XAML преобразует пробелы, символы табуляции и перевода строки в пробелы, а затем сохраняет один пробел, если таковой найден с любого конца непрерывной строки. Полное описание обработки пустого пространства в XAML в этом разделе не рассматривается. Дополнительные сведения см. в разделе Обработка пробелов в XAML.
Дополнительные сведения о синтаксисе XAML
Синтаксис неявных коллекций и свойства содержимого XAML являются функциями языка XAML, позволяющими опускать определенные выводимые теги. Цель этих функций — сделать отношения родитель-потомок для элементов на странице более видимыми при разработке или проверке разметки.
Дополнительные сведения о синтаксисе атрибутов и синтаксисе элементов свойств, а также о других терминах, используемых при описании синтаксиса XAML во всей документации Пакет SDK см. в разделе Терминология синтаксиса XAML. Раздел Терминология синтаксиса XAML также является оптимальным для ознакомления, если планируется использование XAML при создании пользовательского класса.
Корневые элементы XAML и пространства имен XML
Файл XAML должен иметь только один корневой элемент, чтобы одновременно быть корректным файлом XML и допустимым файлом XAML. Обычно следует выбрать элемент, который является частью модели приложения (например, Window или Page для страницы, ResourceDictionary для внешнего словаря или Application для корня определения приложения). В следующем примере приведен корневой элемент обычного файла XAML для страницы WPF с корневым элементом Page.
<Page
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
...
</Page>
Корневой элемент также содержит атрибуты xmlns и xmlns:x. Эти атрибуты указывают на обработчик XAML, пространства имен XML которого содержат определения элементов для элементов, на которые будет ссылаться разметка. Атрибут xmlns специально указывает пространство имен XML по умолчанию. В пределах пространства имен XML по умолчанию объектные элементы в разметке можно указывать без префикса. Для большинства сценариев приложений WPF и практически для всех примеров, приведенных в разделах WPF Пакет SDK, пространство имен XML по умолчанию сопоставлено пространству имен WPF https://schemas.microsoft.com/WinFX/2006/XAML/Presentation. Атрибут xmlns:x указывает дополнительное пространство имен XML, которое сопоставлено пространству имен https://schemas.microsoft.com/winfx/2006/xaml языка XAML. Требуемые компоненты языка, определенные спецификацией XAML, употребляются с префиксом x: при ссылке в разметке файла в этом сопоставлении. Это использование xmlns для определения области для использования и сопоставления является согласованным со спецификацией XML 1.0. Обратите внимание, что атрибуты xmlns строго необходимы только для корневого элемента каждой страницы и в определении приложения, если оно предоставлено в разметке. Определения xmlns будут применяться ко всем дочерним элементам корня (такое поведение также согласовано со спецификацией XML 1.0 для xmlns.) Атрибуты xmlns также разрешены для других элементов ниже корня и будут применены ко всем дочерним элементам определяющего элемента. Однако подобное использование не типично, так как частое определение или переопределение пространств имен XML может осложнить читаемость разметки XAML.
Известно, что сборки WPF содержат типы, поддерживающие сопоставления пространствам имен XML WPF по умолчанию ввиду того, что конфигурация является частью файла построения проекта. Сборки также сопоставляются в файлах целей. Таким образом, сопоставление xmlns — это все, что нужно, чтобы ссылаться на элементы XAML, полученные из сборок WPF. Для собственных пользовательских сборок или для сборок вне WPF можно указать сборку как часть сопоставления xmlns. Как правило, выбирается другой префикс, но также возможно выбрать другое пространство имен XML по умолчанию и затем сопоставить WPF с префиксом. Дополнительные сведения об отношении пространств имен XML и пространств имен фонового кода в сборках см. в разделе Пространства имен XAML и сопоставление пространств имен.
Префикс "x:"
В предыдущем примере корневого элемента префикс x: использовался для сопоставления пространства имен XML XAML https://schemas.microsoft.com/winfx/2006/xaml. Префикс x: будет использоваться для сопоставления пространства имен XML XAML в шаблонах для проектов, в примерах и в документации по всему этому Пакет SDK. Префикс x: / XAML пространства имен XML содержит некоторые конструкции программирования, которые будут достаточно часто использоваться в XAML. Ниже приведен список наиболее часто используемых конструкций программирования пространства имен префикс x: / XAML:
x:Key: задает уникальный ключ для каждого ресурса в ResourceDictionary. x:Key скорее всего будет применяться в 90% случаев использования x: в разметке приложения.
x:Class: задает имя пространства имен CLR и имя класса для класса, предоставляющего код программной части для страницы XAML. Такой класс должен присутствовать для поддержки с выделенным кодом, и именно по этой причине почти всегда есть сопоставление x:, даже при отсутствии ресурсов.
x:Name: задает имя объекта во время выполнения для экземпляра, который существует в коде во время выполнения после обработки объектного элемента. x:Name используется для случаев именования элементов, когда эквивалентное свойство Name уровня среды WPF не поддерживается. Это происходит в некоторых сценариях анимации.
x:Static: включает ссылку на значение, которая возвращает статическое значение, в противном случае не являющееся свойством, совместимым с XAML.
x:Type: создает ссылку Type на основе имени типа. Это используется для задания атрибутов, которые принимают типы Type, например, Style.TargetType, хотя во многих случаях это свойство имеет встроенное преобразование из строки в Type, таким образом, использование x:Type необязательно.
Существуют дополнительные конструкции программирования для префикса пространства имен x: / XAML, которые применяются не так часто. Дополнительные сведения см. в разделе Возможности пространства имен языка XAML (x:).
События и код программной части XAML
Большинство приложений WPF состоит и из разметки, и из с выделенным кодом. В проекте XAML записывается как файл с расширением XAML, а для записи файла с выделенным кодом используется язык CLR, например Microsoft Visual Basic .NET или C#. При компиляции файла XAML расположение файла с выделенным кодом XAML для каждой страницы XAML идентифицируется указанием пространства имен и класса как атрибута x:Class корневого элемента страницы XAML.
В приведенных примерах было использовано несколько кнопок, но ни с одной из этих кнопок не было ассоциировано логическое поведение. Первичным механизмом добавления поведения для объектного элемента на уровне приложения является использование существующего события элементного класса и написание специального обработчика для этого события, которое вызывается при возникновении этого события во время выполнения. Имя события и имя обработчика для использования указываются в разметке, тогда как код, который реализует обработчик, определен в фоновом коде.
<Page
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
x:Class="MyNamespace.MyPageCode">
<Button Click="ClickHandler" >Click Me!</Button>
</Page>
namespace MyNamespace
{
public partial class MyPageCode
{
void ClickHandler(object sender, RoutedEventArgs e)
{
Button b = e.Source as Button;
b.Background = Brushes.Red;
}
}
}
Обратите внимание, что файл с выделенным кодом использует пространство имен CLR MyNamespace и объявляет MyPageCode как частичный класс в этом пространстве имен. Это аналогично значению атрибута x:Class MyNamespace.MyPageCode, предоставленному в корне разметки. Компилятор автоматически создаст частичный класс для любой скомпилированной страницы XAML путем создания класса, производного от типа корневого элемента. При предоставлении фонового кода, который также определяет тот же частичный класс, результирующий код объединяется внутри того же пространства имен и класса скомпилированного приложения.
Дополнительные сведения о требованиях написания фонового кода см. в подразделе "Код программной части, обработчик событий и требования частичного класса" раздела Выделенный код и XAML.
Если создание отдельного файла с выделенным кодом нежелательно, то можно также встроить код в файле XAML. Однако встроенный код является менее гибким методом, имеющим значительные ограничения. Дополнительные сведения см. в разделе Выделенный код и XAML.
Синтаксис атрибутов событий
При задании поведения в разметке через события обычно для присоединения обработчиков используется синтаксис атрибутов. Объектный элемент, для которого указан атрибут события, становится экземпляром, отслеживающим это событие и вызывающим обработчик. Имя того события, которое необходимо обработать — имя атрибута. Значение атрибута — это имя метода обработчика, который будет определен. Затем необходимо предоставить реализацию обработчика в фоновом коде, обработчик будет основываться на делегате для этого события. Обработчик пишется в фоновом коде на языке программирования, например, Microsoft Visual Basic .NET или C#.
Каждое событие WPF при возникновении отобразит свои данные. Обработчики событий могут получить доступ к данным этого события. В предыдущем примере обработчик получает источник события через данные событий, а затем устанавливает свойства для этого источника.
Маршрутизируемые события
Уникальной и основной возможностью для WPF, является перенаправленное событие. Перенаправленные события позволяет элементу обрабатывать событие, которое было вызвано другим элементом, пока они связаны через отношение дерева элементов. При задании обработки события атрибутом XAML перенаправленное событие может отслеживаться и обрабатываться любым элементом, включая те, для которых это событие не указано в таблице членов класса. Это достигается путем уточнения атрибута имени события именем класса-владельца. Например, родительский StackPanel в текущем примере StackPanel / Button может зарегистрировать обработчик для события Click кнопки дочернего элемента путем задания атрибута Button.Click для объектного элемента StackPanel именем обработчика в качестве значения атрибута. Дополнительные сведения см. в разделе Общие сведения о перенаправленных событиях.
x:Name
По умолчанию экземпляр объекта, который создается при обработке объектного элемента, не обладает уникальным идентификатором или встроенной ссылкой на объект, которые можно использовать в коде. Если конструктор вызывается в коде, почти всегда для задания переменной созданным экземпляром используется результат конструктора, так что можно сослаться на экземпляр позднее в коде. Для предоставления стандартизованного доступа к объектам, созданным через определение разметки, XAML определяет атрибут x:Name. Можно задать значение атрибута x:Name для любого объектного элемента. В коде программной части выбранный идентификатор эквивалентен переменной экземпляра, которая ссылается на созданный экземпляр. По всем параметрам именованные элементы работают, как если бы они были экземплярами объекта (имя только ссылается на этот экземпляр), и в приложении фоновый код может ссылаться на именованные элементы для обработки взаимодействий во время выполнения.
Элементы XAML уровня среды WPF наследуют свойство Name, являющееся эквивалентным определенному в XAML атрибуту x:Name. Некоторые другие классы также предоставляют эквиваленты уровня свойств для x:Name, который также обычно определяется как свойство Name. В целом, если не удается найти свойство Name в таблице членов для выбранного элемента, следует использовать вместо этого x:Name.
В следующем примере задается Name для элемента StackPanel. Затем обработчик для Button в StackPanel ссылается на StackPanel через его buttonContainer ссылок на экземпляры, как задано в Name.
<StackPanel Name="buttonContainer">
...
<Button Click="RemoveThis">Click to remove this button</Button>
</StackPanel>
void RemoveThis(object sender, RoutedEventArgs e)
{
FrameworkElement fe = e.Source as FrameworkElement;
if (buttonContainer.Children.Contains(fe))
{
buttonContainer.Children.Remove(fe);
}
}
Так же, как переменная, имя для экземпляра управляется понятием области, чтобы имена могли быть уникальными в пределах определенной прогнозируемой области. Основная разметка, определяющая страницу, обозначает одну уникальную область видимости имен с корневым элементом страницы в качестве границ. Однако другие источники разметки могут взаимодействовать со страницей во время выполнения, например, стили или шаблоны в стилях, и такие источники разметки часто имеют свои собственные области видимости имен, не обязательно связанные с областью видимости имен страницы. Дополнительные сведения о x:Name и областях видимости имен см. в разделах Name, Атрибут x:Name и Область видимости имен WPF.
Вложенные свойства и события
XAML предоставляет языковую возможность, позволяющую задавать определенные свойства или события для любого элемента, независимо от того, существует ли свойство или элемент в таблице членов для элемента, для которого происходит установка. Версия свойств этой возможности называется вложенное свойство, версия событий называется вложенное событие. Концептуально можно представить вложенные свойства и события как глобальные члены, которые могут быть установлены для любого элемента или класса, независимо от его иерархии классов.
Вложенные свойства в XAML обычно используются с помощью синтаксиса атрибутов. В синтаксисе атрибутов можно указать вложенное свойство в форме OwnerType.PropertyName. Внешне это напоминает использование элементов свойств, но в этом случае задаваемый OwnerType всегда является типом, отличным от объектного элемента, для которого задается вложенное свойство. OwnerType является типом, предоставляющим методы доступа, которые необходимы обработчику XAML для получения или установки значения вложенного свойства. Наиболее распространенным сценарием для вложенных свойств является разрешение дочерним элементам предоставления значения свойства их родительскому элементу.
В следующем примере показано вложенное свойство DockPanel.Dock. Класс DockPanel определяет методы доступа для DockPanel.Dock и поэтому владеет вложенным свойством. Класс DockPanel также содержит логику, которая выполняет итерацию его дочерних элементов и специально проверяет каждый элемент на набор значений DockPanel.Dock. Если значение обнаруживается, это значение используется в процессе разметки для расположения дочерних элементов. Использование вложенного свойства DockPanel.Dock и возможности размещения на самом деле является мотивирующим сценарием для класса DockPanel.
<DockPanel>
<Button DockPanel.Dock="Left" Width="100" Height="20">I am on the left</Button>
<Button DockPanel.Dock="Right" Width="100" Height="20">I am on the right</Button>
</DockPanel>
В Windows Presentation Foundation (WPF) все вложенные свойства также реализуются как свойства зависимости. Дополнительные сведения см. в разделе Общие сведения о вложенных свойствах зависимостей.
Вложенные события используют аналогичную форму OwnerType.EventName синтаксиса атрибутов. Так же, как не вложенные события, значение атрибута для вложенного события в XAML задает имя метода обработчика, который вызывается, когда событие обрабатывается для элемента.
Одним из сценариев, где используются вложенные события, является сценарий для событий ввода с устройств, которые могут быть обработаны для любых элементов, например, кнопок мыши. Примером такого вложенного события является Mouse.MouseDown. Тем не менее, большая часть элементов уровня среды WPF может использовать это событие без использования вложенного события. Это происходит потому, что базовый элементный класс UIElement создает псевдоним для вложенного события Mouse.MouseDown и представляет этот псевдоним в таблице членов UIElement (как MouseDown). В результате обычно не обязательно использовать синтаксис вложенных событий на странице XAML или в программировании приложения Windows Presentation Foundation (WPF). Исключениями являются случаи использования настраиваемых элементов или объектных элементов, не производных от UIElement, но по-прежнему имеющих визуальное представление (такие случаи редки). В WPF все вложенные события также реализуются как перенаправленные события. ContentElement также предоставляет псевдонимы для событий ввода для использования в документационной модели потока. Дополнительные сведения см. в разделах Общие сведения о перенаправленных событиях и Общие сведения о входных данных.
Составляющие корневого элемента страницы XAML
В следующей таблице показано типичное подразделение корневого элемента страницы XAML, отображающее определенные атрибуты корневого элемента, рассмотренные в этом разделе:
<Page |
Открытие объектного элемента корневого элемента |
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" |
Пространство имен по умолчанию (WPF) |
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml" |
Пространство имен XAML |
x:Class="MyNamespace.MyPageCode" |
Объявление частичного класса, связывающего разметку с любым фоновым кодом, определенным в этом же частичном классе |
> |
Конец объектного элемента корня, еще не закрытого, поскольку страница содержит дочерние элементы |
Базовые классы и XAML
Базовый класс XAML и его схемы представляют собой набор классов, которые соответствуют объектам CLR, а также элементам разметки, которые используются в XAML. Однако не все классы могут сопоставляться с элементами. Абстрактные классы, например, ButtonBase, и некоторые не абстрактные базовые классы используются для наследования в модели объектов CLR и не поддерживают соответствующие теги разметки XAML. Базовые классы, включая абстрактные, по-прежнему важны для разработки XAML, так как каждый из элементов XAML наследует члены некоторого базового класса в своей иерархии. Зачастую эти члены включают свойства, которые могут быть заданы как атрибуты элемента, или события, которые могут быть обработаны. Класс FrameworkElement является конкретным базовым классом Пользовательский интерфейс в WPF на уровне среды WPF. При разработке Пользовательский интерфейс следует использовать различные классы фигур, панелей, декораторов или элементов управления, которые являются производными от FrameworkElement. Связанный базовый класс, FrameworkContentElement, поддерживает элементы, ориентированные на документы, которые подходят для представления макета потока, используя API-интерфейсы, намеренно дублирующие API-интерфейсы в FrameworkElement. Сочетание атрибутов на уровне элементов и объектная модель CLR предоставляет набор общих свойств, устанавливаемых для большинства конкретных элементов XAML, независимо от конкретного типа элементов и базового класса.
Безопасность в XAML
XAML — это язык разметки, непосредственно представляющий создание экземпляра объекта и его выполнение. Таким образом, элементы, созданные в XAML, имеют такие же возможности взаимодействия с системными ресурсами (сетевой доступа, ввод-вывод файловой системы, например), как и эквивалентный созданный код.
WPF поддерживает CAS (Code Access Security — безопасность доступа кода) структуры безопасности NET. Это означает, что содержимое WPF, работающее в зоне "Интернет", сократило разрешения исполнения. "Свободный XAML" (страницы неоткомпилированного XAML, интерпретируемые во время загрузки средства просмотра XAML) и XBAP (XAML browser application — приложение обозревателя XAML) обычно выполняются в этой в зоне "Интернет" и используют тот же набор разрешений. Однако XAML, загруженный в приложения с уровнем полного доверия, имеет такой же доступ к системным ресурсам, как и ведущее приложение. Дополнительные сведения см. в разделе Безопасность частичного доверия Windows Presentation Foundation.
Загрузка XAML из кода
XAML можно использовать для определения всего пользовательского интерфейса, но иногда также уместно определение только его части в XAML. Эта возможность может использоваться для включения частичной настройки, локального хранения данных, использования XAML для предоставления бизнес-объекта или различных возможных сценариев. Ключом для этих сценариев является класс XamlReader и его метод Load. Входные данные являются файлом XAML, а выходными данными — объект, представляющий во время выполнения целое дерево объектов, созданных из разметки. Можно затем вставить объект, который будет свойством другого объекта, уже существующего в приложении. Пока свойство является соответствующим свойством в модели содержимого, которая имеет возможности отображения и которая уведомит ядро выполнения, что новое содержимое было добавлено в приложение, можно достаточно легко изменить содержимое работающего приложения путем загрузки в XAML. Обратите внимание, что эта возможность доступна только в приложениях с уровнем полного доверия из-за очевидных с точки зрения безопасности последствий загрузки файлов в работающие приложения.
Что дальше?
В этом разделе представлено введение в понятия и терминологию синтаксиса XAML. Дополнительные сведения о терминах, использованных здесь, см. в разделе Терминология синтаксиса XAML.
Если вы еще не ознакомились с этими сведениями, ознакомьтесь с руководством Введение в Windows Presentation Foundation. Создание приложения разметки, описанного в учебнике, поможет лучше осознать многие основные понятия, описанные в этом разделе.
WPF использует конкретную модель приложения, основанную на классе Application. Дополнительные сведения см. в разделе Общие сведения об управлении приложением.
В Построение приложения WPF представлены дополнительные сведения о том, как построить включающее XAML приложения из командной строки и в Microsoft Visual Studio.
В Общие сведения о свойствах зависимости представлены дополнительные сведения о разнообразии свойств в Windows Presentation Foundation (WPF) и описано понятие свойств зависимости.
Наконец, средство редактирования XAML, которое называется XAMLPad, включено в пакет SDK. Это средство можно использовать для экспериментирования с XAML в режиме реального времени.
См. также
Основные понятия
Язык XAML и пользовательские классы
Общие сведения о базовых элементах
Другие ресурсы
Возможности пространства имен языка XAML (x:)