Общие сведения о языке XAML (WPF)

В этом разделе описаны возможности языка XAML и показано, как можно использовать язык XAML для написания приложений Windows Presentation Foundation (WPF). В частности, в этом разделе описывается реализация XAML в WPF. Сам язык XAML — это более широкое понятие языка, чем WPF.

В этом разделе содержатся следующие подразделы.

  • Общие сведения о XAML
  • Краткое описание синтаксиса языка XAML
  • Чувствительность к регистру и пробелам в XAML
  • Расширения разметки
  • Преобразователи типов
  • Корневые элементы XAML и пространства имен XAML
  • Пользовательские префиксы и пользовательские типы в XAML
  • События и код программной части XAML
  • Именованные события XAML
  • Вложенные свойства и события
  • Базовые типы и язык XAML
  • Безопасность в XAML
  • Загрузка XAML из кода
  • Что дальше?
  • Связанные разделы

Общие сведения о XAML

XAML — это декларативный язык разметки. С точки зрения модели программирования .NET Framework язык XAML упрощает создание UI для приложения .NET Framework. Можно создать видимые элементы UI в декларативной разметке XAML, а затем отделить определение UI от логики времени выполнения, используя файлы кода программной части, присоединенные к разметке с помощью определений разделяемых классов. Язык XAML напрямую представляет создание экземпляров объектов в конкретном наборе резервных типов, определенных в сборках. В этом заключается его отличие от большинства других языков разметки, которые, как правило, представляют собой интерпретируемые языки без прямой связи с системой резервных типов. Язык XAML обеспечивает рабочий процесс, позволяющий нескольким участникам разрабатывать UI и логику приложения, используя потенциально различные средства.

При представлении в виде текста файлы XAML являются XML-файлами, которые обычно имеют расширение .xaml. Файлы можно сохранять в любой кодировке, поддерживаемой для XML, но обычно используется кодировка UTF-8.

В следующем примере показано, как можно создать кнопку как часть UI. Этот пример дает лишь общее представление о том, как в языке XAML представлены распространенные метафоры программирования для такого объекта как UI (это не полный пример).

<StackPanel>
  <Button Content="Click Me"/>
</StackPanel>

Краткое описание синтаксиса языка XAML

В следующих разделах приводится описание основных форм синтаксиса XAML и короткий пример разметки. В этих разделах не приводится полная информация о каждой форме синтаксиса (например, представление в системе резервных типов). Дополнительные сведения об особенностях синтаксиса XAML для каждой формы синтаксиса, представленной в этом разделе, см. в разделе Подробное описание синтаксиса XAML.

Значительная часть материалов в следующих нескольких разделах будет уже знакома тем, кто имеет опыт работы с языком XML. Это обусловлено базовыми принципами разработки языка XAML. В языке XAML определяются собственные структуры, однако в них используются язык и форма разметки XML.

Объектные элементы XAML

Объектный элемент обычно объявляет экземпляр типа. Этот тип определен в сборках, предоставляющих резервные типы для технологии, в которой XAML используется как язык.

Синтаксис объектного элемента всегда начинается с открывающейся угловой скобки (<). За ней следует имя типа, для которого требуется создать экземпляр. (Имя может содержать префикс. Описание этого понятия будет приведено далее.) После этого при необходимости можно объявить атрибуты объектного элемента. Для завершения тега объектного элемента введите закрывающую угловую скобку (>). Вместо этого можно использовать самозакрывающуюся форму, в которой отсутствует содержимое, установив в конце тега косую черту и закрывающую угловую скобку (/>). Например, снова рассмотрим предыдущий фрагмент разметки.

<StackPanel>
  <Button Content="Click Me"/>
</StackPanel>

В нем указано два объектных элемента: <StackPanel> (с содержимым и последующим закрывающим тегом) и <Button .../> (самозакрывающаяся форма с несколькими атрибутами). Объектные элементы StackPanel и Button сопоставлены с именем класса, определенным WPF и являющимся частью сборок WPF. При задании тега объектного элемента создается инструкция обработки XAML для создания нового экземпляра. Каждый экземпляр создается путем вызова конструктора базового типа или структуры по умолчанию при синтаксическом анализе и загрузке XAML-кода.

Синтаксис атрибутов (свойства)

Свойства объекта часто можно выразить в виде атрибутов объектного элемента. Синтаксис атрибутов называет свойство, задаваемое в синтаксисе атрибутов, после чего следует оператор назначения (=). Значение атрибута всегда задается как строка, заключенная в кавычки.

Синтаксис атрибутов — это наиболее простой синтаксис задания свойств, интуитивно понятный разработчикам, которые раньше использовали языки разметки. Например, следующая разметка создает кнопку с красным текстом и синим фоном и отображает текст, заданный как Content.

<Button Background="Blue" Foreground="Red" Content="This is a button"/>

Синтаксис элемента свойства

Для некоторых свойств объектного элемента невозможен синтаксис атрибутов, так как объект или сведения, необходимые для задания значения свойства, не могут быть адекватно представлены в строке, указываемой в кавычках, с соблюдением ограничений синтаксиса атрибутов. В этих случаях может использоваться другой синтаксис — синтаксис элементов свойств.

Для открывающего тега элемента свойства используется следующий синтаксис: <имя_типа.имя_свойства>. В большинстве случаев содержимое тега является объектным элементом типа, к которому может принадлежать значение этого свойства. Указав содержимое, необходимо завершить элемент свойства закрывающим тегом. Для закрывающего тега используется синтаксис </имя_типа.имя_свойства>.

Если допустим синтаксис атрибутов, его использование, как правило, более удобно и приводит к созданию более компактной разметки, но часто выбор связан только со стилем, а не с техническими ограничениями. В следующем примере те же свойства задаются так же, как в предыдущем примере синтаксиса атрибутов, но на этот раз с помощью синтаксиса элементов свойств для всех свойств 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 включает некоторые оптимизации, делающие разметку удобнее для человеческого восприятия. Одна из оптимизаций заключается в том, что если определенное свойство принимает тип коллекции, элементы, объявленные в разметке как дочерние в пределах значения этого свойства, становятся частью коллекции. В этом случае коллекция дочерних объектных элементов является значением, которое задается для свойства коллекции.

В следующем примере показан синтаксис коллекции для задания значений свойства GradientStops.

<LinearGradientBrush>
  <LinearGradientBrush.GradientStops>
    <!-- no explicit new GradientStopCollection, parser knows how to find or create -->
    <GradientStop Offset="0.0" Color="Red" />
    <GradientStop Offset="1.0" Color="Blue" />
  </LinearGradientBrush.GradientStops>
</LinearGradientBrush>

Свойства содержимого XAML

XAML указывает функцию языка, за счет чего класс может назначить только одно из своих свойств как свойство содержимого XAML. Дочерние элементы данного объектного элемента используются для задания значения этого свойства содержимого. Другими словами, для свойства содержимого (и только для него) можно опустить элемент свойства, указав это свойство в XAML-разметке, и тем самым создать более наглядную метафору родительского/дочернего элементов в разметке.

Например, Border указывает свойство содержимого Child. Следующие два элемента Border обрабатываются одинаковым образом. Первый элемент использует преимущества синтаксиса свойства содержимого и опускает элемент свойства Border.Child. Второй элемент явно показывает Border.Child.

<Border>
  <TextBox Width="300"/>
</Border>
<!--explicit equivalent-->
<Border>
  <Border.Child>
    <TextBox Width="300"/>
  </Border.Child>
</Border>

Для языка XAML действует следующее правило: значение свойства содержимого XAML должно быть задано полностью либо до, либо после любых других элементов свойств данного объектного элемента. Например, следующая разметка не компилируется:

<Button>I am a 
  <Button.Background>Blue</Button.Background>
  blue button</Button>

Дополнительные сведения об этом ограничении свойств содержимого XAML см. в подразделе "Свойства содержимого XAML" раздела Подробное описание синтаксиса XAML.

Текстовое содержимое

Небольшое количество элементов XAML могут непосредственно обрабатывать текст как содержимое. Это происходит в одной из следующих ситуаций.

  • Класс должен объявить свойство содержимого, а это свойство содержимого должно принадлежать к типу, присваиваемому строке (тип может быть Object). Например, любой класс ContentControl использует свойство Content как свойство содержимого, принадлежащее к типу Object, и поддерживает следующее использование в практическом классе ContentControl, например Button: <Button>Hello</Button>.

  • Тип должен объявлять преобразователь типов, при этом текстовое содержимое используется как текст инициализации для данного преобразователя типов. Например, <Brush>Blue</Brush>. Этот случай на практике встречается реже.

  • Тип должен быть известным типом-примитивом языка XAML.

Объединение свойств содержимого и синтаксиса коллекции

Рассмотрим следующий пример.

<StackPanel>
  <Button>First Button</Button>
  <Button>Second Button</Button>
</StackPanel>

Здесь каждый Button является дочерним элементом StackPanel. Это рациональная и интуитивно понятная разметка, в которой опущены два тега по двум разным причинам.

  • Опущен элемент свойства StackPanel.Children: StackPanel наследуется от Panel. Panel определяет Panel.Children как свойство содержимого XAML.

  • Опущен объектный элемент UIElementCollection: свойство Panel.Children принимает тип UIElementCollection, реализующий IList. Тег элемента коллекции можно опустить на основании правил XAML, касающихся обработки коллекций, например IList. (В этом случае UIElementCollection фактически не может быть создан, поскольку он не предоставляет конструктор по умолчанию, и поэтому объектный элемент UIElementCollection показан закомментированным.)

<StackPanel>
  <StackPanel.Children>
    <!--<UIElementCollection>-->
    <Button>First Button</Button>
    <Button>Second Button</Button>
    <!--</UIElementCollection>-->
  </StackPanel.Children>
</StackPanel>

Синтаксис атрибутов (события)

Синтаксис атрибутов также можно использовать для элементов, которые являются событиями, а не свойствами. В этом случае имя атрибута является именем события. События для языка XAML реализованы в WPF таким образом, что значение атрибута является именем обработчика, реализующего делегат этого события. Например, в следующей разметке назначается обработчик для события Click класса Button, созданного в разметке.

<Page 
  xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
  x:Class="ExampleNamespace.ExamplePage">
  <Button Click="Button_Click" >Click Me!</Button>
</Page>

Помимо этого примера синтаксиса атрибутов имеется больше информации по событиям и XAML в WPF. Например, может возникнуть вопрос, что представляет и как определяется указанный здесь атрибут ClickHandler. Ответ на этот вопрос можно найти в следующем подразделе данного раздела.

Чувствительность к регистру и пробелам в XAML

Вообще говоря, в языке XAML учитывается регистр символов. При разрешении резервных типов в WPF XAML регистр учитывается по тем же правилам, что и для CLR. Объектные элементы, элементы свойств и имена атрибутов должны быть указаны с учетом регистра символов при сравнении по имени с базовым типом в сборке или с элементом типа. В ключевых словах и примитивах в языке XAML также учитывается регистр. В значениях регистр учитывается не всегда. Учет регистра для значений будет зависеть от типа преобразователя поведения, связанного со свойством, которое принимает значение, или с соответствующим типом значения свойства. Например, свойства, принимающие тип Boolean, могут принимать значения true и True как эквивалентные, но только потому, что синтаксический анализатор WPF XAML для преобразования из строкового формата в тип Boolean уже рассматривает их как эквиваленты.

Обработчики и сериализаторы WPF XAML игнорируют или удаляют все незначимые пробелы и выполняют нормализацию всех значимых пробелов. Эти принципы соответствуют стандартным рекомендациям по использованию пробелов, представленных в спецификации языка XAML. Данное поведение типично только при задании строк в свойствах содержимого XAML. Проще говоря, XAML преобразует пробелы, символы табуляции и перевода строки в пробелы, а затем сохраняет один пробел, если таковой найден с любого конца непрерывной строки. Полное описание обработки пробелов в XAML в этом разделе не рассматривается. Дополнительные сведения см. в разделе Обработка пробелов в XAML.

Расширения разметки

Расширения разметки являются понятием языка XAML. При использовании для предоставления значения синтаксиса атрибутов фигурные скобки ({ и }) указывают на использование расширения разметки. При обработке XAML расширения разметки обрабатываются иначе, чем значения атрибутов, обычно рассматриваемые как литеральная строка или как значение, которое может быть преобразовано в строку.

Наиболее распространенными расширениями разметки, используемыми при программировании приложений WPF, являются Binding, используемое для сохранения выражений привязки данных, и ссылки на ресурсы StaticResource и DynamicResource. Используя расширения разметки можно использовать синтаксис атрибутов для указания значений свойств, которые в целом не поддерживают синтаксис атрибутов. В расширениях разметки часто используются промежуточные типы выражений для включения функций, которые присутствуют только во время выполнения, например, откладывание значений или ссылка на другие объекты.

Например, в следующей разметке значение свойства 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>

Список всех расширений разметки для XAML, реализованных в WPF, см. в разделе Расширения XAML WPF. Список расширений разметки, определенных в сборке System.Xaml и более доступных для реализаций XAML платформы .NET Framework, см. в разделе Возможности пространства имен языка XAML (x:). Дополнительные сведения о понятиях расширений разметки см. в разделе Расширения разметки и XAML WPF.

Преобразователи типов

В разделе было отмечено, что должна быть предоставлена возможность задать значение атрибута строкой. Основная собственная обработка преобразования строк в другие типы объектов или простые значения основана на самом типе String, помимо некоторой собственной обработки для определенных типов, например DateTime или Uri. Но многие типы WPF или элементы этих типов расширяют основное поведение обработки атрибутов строк таким образом, что экземпляры более сложных типов объектов могут быть заданы как строки и атрибуты.

Структура Thickness является примером типа, для которого включено преобразование типа для использования XAML. Класс Thickness указывает измерения в рамках вложенного прямоугольника и используется как значение для свойств, таких как Margin. Если поместить преобразователь типов в Thickness, все свойства, использующие Thickness, легче указать в 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 должен иметь только один корневой элемент, чтобы одновременно быть файлом XML с правильным форматом и допустимым файлом XAML. Обычно при работе с WPF используется корневой элемент, наиболее значимый в модели приложения WPF (например, 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, какие пространства имен XAML содержат определения типов для резервных типов, на которые будет ссылаться разметка в качестве элементов. Атрибут xmlns специально указывает пространство имен XAML по умолчанию. В пределах пространства имен XAML по умолчанию объектные элементы в разметке можно указывать без префикса. Для большинства сценариев приложения WPF и практически для всех примеров, приведенных в разделах SDK WPF, пространство имен XAML по умолчанию сопоставлено с пространством имен https://schemas.microsoft.com/winfx/2006/xaml/presentation WPF. Атрибут xmlns:x указывает дополнительное пространство имен XAML, которое сопоставлено пространству имен языка XAML https://schemas.microsoft.com/winfx/2006/xaml.

Это использование атрибутов xmlns для определения области использования и сопоставления области видимости имен согласовано со спецификацией XML 1.0. Области видимости имен XAML отличаются от областей видимости имен XML только тем, что область видимости имен XAML также подразумевает некоторую информацию о резервном копировании элементов области видимости имен по типам в случае разрешения типов и анализа XAML.

Обратите внимание, что атрибуты xmlns строго необходимы только для корневого элемента каждого XAML-файла. Определения xmlns будут применяться ко всем элементам-потомкам корневого элемента (такое поведение также соответствует спецификации XML 1.0 для xmlns). Атрибуты xmlns также разрешены для других элементов ниже корня и будут применены ко всем элементам-потомкам определяющего элемента. Впрочем, частое определение или повторное определение пространств имен XAML может сделать стиль разметки XAML трудным для человеческого восприятия.

В WPF реализация обработчика XAML включает инфраструктуру, содержащую информацию о ключевых сборках WPF. Ключевые сборки WPF содержат типы, поддерживающие сопоставления WPF с пространством имен XAML по умолчанию. Это осуществляется за счет конфигурации, являющейся частью файла построения проекта, построения WPF и систем проекта. Таким образом, объявление пространства имен XAML как xmlns по умолчанию — это все, что нужно, чтобы ссылаться на элементы XAML, полученные из сборок WPF.

Префикс "x:"

В предыдущем примере корневого элемента префикс x: использовался для сопоставления пространства имен XAML https://schemas.microsoft.com/winfx/2006/xaml, которое является выделенным пространством имен XAML, поддерживающим конструкции языка XAML. Префикс x: используется для сопоставления данного пространства имен XAML в шаблонах для проектов, в примерах и в документации по всему этому SDK. Пространство имен XAML для языка XAML содержит несколько конструкций программирования, которые очень часто используются в XAML. Ниже приведен список наиболее распространенных конструкций программирования с префиксом x:, которые могут вам потребоваться.

  • x:Key. Задает уникальный ключ для каждого ресурса в словаре ResourceDictionary (или аналогичных словарях в других платформах). x:Key применяется примерно в 90% случаев использования сопоставления x: в разметке типичных приложений WPF.

  • x:Class. Задает пространство имен CLR и имя класса, предоставляющего код программной части для страницы XAML. Согласно модели программирования WPF, такой класс должен присутствовать для поддержки кода программной части, поэтому сопоставление x: присутствует почти всегда, даже если ресурсы отсутствуют.

  • x:Name: задает имя объекта во время выполнения для экземпляра, который существует в коде во время выполнения после обработки объектного элемента. Как правило, на практике часто используется свойство, определенное в WPF, эквивалентное x:Name. Такие свойства сопоставляются непосредственно с резервным свойством CLR, а потому более удобны для программирования приложений, где код времени выполнения часто используется для поиска именованных элементов из инициализированного XAML-кода. Наиболее типичное из таких свойств — FrameworkElement.Name. x:Name все же можно использовать, когда эквивалентное свойство Name уровня среды WPF не поддерживается в определенном типе. Это происходит в некоторых сценариях анимации.

  • x:Static. Позволяет использовать ссылку, возвращающую статическое значение, в остальном не являющееся свойством, совместимым с XAML.

  • x:Type: создает ссылку Type на основе имени типа. Это используется для задания атрибутов, которые принимают тип Type, например Style.TargetType, хотя часто свойство имеет встроенное преобразование из строки в тип Type и использование расширения разметки x:Type необязательно.

Существуют дополнительные конструкции программирования в пространстве имен XAML/с префиксом x:, которые применяются не так часто. Дополнительные сведения см. в разделе Возможности пространства имен языка XAML (x:).

Пользовательские префиксы и пользовательские типы в XAML

При использовании собственных пользовательских сборок или сборок за пределами заданных в ядре WPF сборок PresentationCore, PresentationFramework и WindowsBase можно указать сборку как часть пользовательского сопоставления xmlns. Затем можно указывать в пользовательском XAML-коде ссылки на типы из этой сборки, если в типе правильно реализована поддержка требуемых средств XAML.

Ниже приведен очень общий пример работы пользовательских префиксов в разметке XAML. Префикс custom определен в теге корневого элемента и сопоставляется с конкретной сборкой, упакованной и доступной в приложении. Эта сборка содержит тип NumericUpDown, который реализуется для поддержки общего использования XAML, а также использования наследования класса, которое можно вставить в данную конкретную точку модели содержимого XAML WPF. Экземпляр этого элемента управления NumericUpDown объявлен как объектный элемент, префикс обеспечивает, что анализатор XAML "знает", какое пространство имен XAML содержит тип, и, следовательно, где находится резервная сборка, содержащая определение типа.

<Page
    xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:custom="clr-namespace:NumericUpDownCustomControl;assembly=CustomLibrary"
    >
  <StackPanel Name="LayoutRoot">
    <custom:NumericUpDown Name="numericCtrl1" Width="100" Height="60"/>
...
  </StackPanel>
</Page>

Дополнительные сведения о пользовательских типах в языке XAML см. в разделе Код XAML и пользовательские классы для WPF.

Дополнительные сведения об отношении пространств имен XML и пространств имен фонового кода в сборках см. в разделе Пространства имен XAML и сопоставление пространств имен для WPF XAML.

События и код программной части XAML

В большинстве приложений WPF содержится как разметка XAML, так и код программной части. В проекте XAML-код записывается как файл с расширением .xaml, а для записи файла с кодом программной части используется язык CLR, например Microsoft Visual Basic или C#. При компиляции разметки в файле XAML (в составе модели приложений и программирования WPF) расположение файла кода программной части для файла 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="ExampleNamespace.ExamplePage">
  <Button Click="Button_Click" >Click Me!</Button>
</Page>
Private Sub Button_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
    Dim b As Button = e.Source
    b.Foreground = Brushes.Red
End Sub
namespace ExampleNamespace
{
  public partial class ExamplePage
  {
    void Button_Click(object sender, RoutedEventArgs e)
    {
      Button b = e.Source as Button;
      b.Foreground = Brushes.Red;
    }
  }
}

Обратите внимание, что файл кода программной части использует пространство имен CLR ExampleNamespace и объявляет ExamplePage как частичный класс в этом пространстве имен. Это аналогично значению атрибута x:Class ExampleNamespace.ExamplePage, предоставленному в корне разметки. Компилятор разметки WPF автоматически создает разделяемый класс для любого скомпилированного файла XAML путем создания класса, унаследованного от типа корневого элемента. При предоставлении фонового кода, который также определяет тот же частичный класс, результирующий код объединяется внутри того же пространства имен и класса скомпилированного приложения.

Дополнительные сведения о требованиях к созданию кода программной части в WPF см. в подразделе "Код программной части, обработчик событий и требования частичного класса" раздела Код программной части и XAML в WPF.

Если создание отдельного файла кода программной части нежелательно, то можно также встроить код в файл XAML. Однако встроенный код является менее гибким методом, имеющим значительные ограничения. Дополнительные сведения см. в разделе Код программной части и XAML в WPF.

Маршрутизируемые события

Одна из наиболее важных возможностей WPF — перенаправленное событие. Перенаправленные события позволяют элементу обрабатывать событие, которое было вызвано другим элементом, пока они связаны через отношение дерева. При задании обработки события атрибутом XAML перенаправленное событие может отслеживаться и обрабатываться любым элементом, включая те, для которых это событие не указано в таблице членов класса. Это достигается путем уточнения атрибута имени события именем класса-владельца. Например, родительский StackPanel в текущем примере StackPanel / Button может зарегистрировать обработчик для события Click кнопки дочернего элемента путем задания атрибута Button.Click для объектного элемента StackPanel именем обработчика в качестве значения атрибута. Дополнительные сведения о принципах работы перенаправленных событий см. в разделе Общие сведения о перенаправленных событиях.

Именованные события XAML

По умолчанию экземпляр объекта, созданный в графе объекта путем обработки объектного элемента XAML, не имеет уникального идентификатора или ссылки на объект. Тогда как если конструктор вызывается в коде, результат конструктора почти всегда используется для указания созданного экземпляра в качестве значения переменной, чтобы на него можно было ссылаться в дальнейшем коде. Для предоставления стандартизованного доступа к объектам, созданным с помощью определения разметки, в языке XAML определяется атрибут x:Name. Можно задать значение атрибута x:Name для любого объектного элемента. В коде программной части выбранный идентификатор эквивалентен переменной экземпляра, которая ссылается на созданный экземпляр. Именованные элементы во всех отношениях действуют так, как если бы они были экземплярами объекта (имя только ссылается на этот экземпляр), и в приложении код программной части может ссылаться на именованные элементы для обработки взаимодействий времени выполнения. Эта связь между экземплярами и переменными обеспечивается компилятором разметки WPF XAML, и, в частности, использует такие функции как InitializeComponent, подробно не рассматриваемые в этом разделе.

Элементы XAML уровня среды WPF наследуют свойство Name, являющееся эквивалентным определенному в XAML атрибуту x:Name. Некоторые другие классы также предоставляют эквиваленты уровня свойств для x:Name, который также обычно определяется как свойство Name. Вообще говоря, если не удается найти свойство Name в таблице членов для выбранного элемента/типа, вместо него следует использовать атрибут x:Name. Значения x:Name обеспечивают идентификатор элемента XAML, который может использоваться во время выполнения (либо определенными подсистемами, либо вспомогательными методами, такими как FindName).

В следующем примере задается Name для элемента StackPanel. Затем обработчик для Button в StackPanel ссылается на StackPanel через его buttonContainer ссылок на экземпляры, как задано в Name.

<StackPanel Name="buttonContainer">


...


  <Button Click="RemoveThis">Click to remove this button</Button>
</StackPanel>
 Private Sub RemoveThis(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
     Dim fe As FrameworkElement = e.Source
     If (buttonContainer.Children.Contains(fe)) Then
         buttonContainer.Children.Remove(fe)
     End If
End Sub
void RemoveThis(object sender, RoutedEventArgs e)
{
    FrameworkElement fe = e.Source as FrameworkElement;
    if (buttonContainer.Children.Contains(fe))
    {
        buttonContainer.Children.Remove(fe);
    }
}

Как и в случае с переменными, имена экземпляров классов XAML регулируются понятием области, так что обеспечивается уникальность имен в пределах определенной области с известными границами. Основная разметка, определяющая страницу, обозначает одну уникальную область видимости имен XAML с корневым элементом страницы в качестве границы. Однако другие источники разметки могут взаимодействовать со страницей во время выполнения, например стили или шаблоны в стилях, и такие источники разметки часто имеют свои собственные области видимости имен XAML, не обязательно связанные с областью видимости имен XAML страницы. Дополнительные сведения о x:Name и областях видимости имен XAML см. в разделе Name, Директива x:Name или Области видимости имен XAML в WPF.

Вложенные свойства и события

Одна из возможностей языка XAML позволяет задавать для любого элемента определенные свойства или события, независимо от того, существует ли свойство или событие в таблице определений типа для этого элемента. Версия свойств этой возможности называется вложенное свойство, версия событий называется вложенное событие. Концептуально можно представить вложенные свойства и события как глобальные члены, которые могут быть заданы для любого элемента/экземпляра объекта XAML. Впрочем, этот элемент/класс (или более крупная инфраструктура) должен поддерживать резервное хранилище свойств для вложенных значений.

Вложенные свойства в языке XAML обычно используются через синтаксис атрибутов. В синтаксисе атрибутов можно указать вложенное свойство в виде тип_владельца.имя_свойства.

Внешне это напоминает использование элементов свойств, но в данном случае задаваемый тип 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>

В WPF большинство вложенных свойств (или все такие свойства) также реализуются как свойства зависимости. Дополнительные сведения см. в разделе Общие сведения о вложенных свойствах зависимостей.

Вложенные события используют аналогичную форму тип_владельца.имя_события синтаксиса атрибутов. Подобно невложенным событиям, значение атрибута для вложенного события в XAML задает имя метода обработчика, который вызывается, когда событие обрабатывается для элемента. Использование вложенного события в XAML WPF менее распространено. Дополнительные сведения см. в разделе Общие сведения о вложенных событиях.

Базовые типы и язык XAML

Базовая платформа XAML WPF и его пространство имен XAML представляют собой коллекцию типов, которые соответствуют объектам CLR, а также элементы разметки для XAML. Однако не все классы могут сопоставляться с элементами. Абстрактные классы, например ButtonBase, и некоторые неабстрактные базовые классы используются для наследования в модели объектов CLR. Базовые классы, включая абстрактные, по-прежнему важны для разработки XAML, так как каждый из элементов XAML наследует члены некоторого базового класса в своей иерархии. Часто эти члены включают в себя свойства, которые могут быть заданы как атрибуты элемента или как события, на которые можно реагировать. FrameworkElement — конкретный базовый класс компонента UI WPF на уровне инфраструктуры WPF. При разработке UI следует использовать различные классы фигур, панелей, декораторов или элементов управления, которые являются производными от FrameworkElement. Связанный базовый класс, FrameworkContentElement, поддерживает элементы, ориентированные на документы, которые подходят для представления макета потока, используя APIs, намеренно дублирующие APIs в FrameworkElement. Сочетание атрибутов на уровне элементов и объектной модели CLR обеспечивает набор общих свойств, которые можно задать для большинства конкретных элементов XAML, независимо от типа элемента XAML и его базового типа.

Безопасность в XAML

XAML — это язык разметки, непосредственно представляющий создание и выполнение объекта. Таким образом, элементы, созданные в XAML, имеют такие же возможности взаимодействия с системными ресурсами (например, сетевой доступ и ввод-вывод файловой системы), как и эквивалентный порожденный код.

WPF поддерживает Code Access Security (CAS) платформы безопасности .NET Framework 4. Это означает, что содержимое WPF, работающее в зоне "Интернет", сократило разрешения исполнения. " Свободный XAML" (страницы некомпилированного XAML, интерпретируемые во время загрузки средства просмотра XAML) и XAML browser application (XBAP) обычно выполняются в этой Интернет-зоне и используют один набор разрешений. Однако XAML, загруженный в полностью доверенное приложение, имеет такой же доступ к системным ресурсам, как и ведущее приложение. Дополнительные сведения см. в разделе Безопасность частичного доверия в WPF.

Загрузка XAML из кода

XAML можно использовать для определения всего пользовательского интерфейса, но иногда также уместно определение в XAML только его части. Эта возможность может использоваться для включения частичной настройки, локального хранения данных, использования XAML для предоставления бизнес-объекта или различных возможных сценариев. Ключом для этих скриптов является класс XamlReader и его метод Load. Входные данные являются файлом XAML, а выходные данные — объектом, представляющим дерево объектов времени выполнения, созданных по разметке. Можно затем вставить объект, который будет свойством другого объекта, уже существующего в приложении. Пока свойство является допустимым свойством в модели содержимого, которая имеет возможности отображения и которая уведомляет ядро выполнения о добавлении в приложение нового содержимого, можно достаточно легко изменить содержимое работающего приложения путем загрузки XAML. Обратите внимание, что эта возможность доступна только в приложениях с уровнем полного доверия из-за очевидных с точки зрения безопасности последствий загрузки файлов в работающие приложения.

Что дальше?

Этот раздел содержит вводные сведения о терминологии и понятиях синтаксиса в XAML применительно к WPF. Дополнительные сведения об используемых здесь терминах см. в разделе Подробное описание синтаксиса XAML.

Выполните упражнения из раздела руководства Пошаговое руководство. Начало работы с WPF, если вы не сделали этого ранее. При создании приложения, ориентированного на разметку и описанного в руководстве, упражнения помогут лучше осознать многие понятия, описанные в этом разделе.

WPF использует конкретную модель приложения, основанную на классе Application. Дополнительные сведения см. в разделе Общие сведения об управлении приложением.

В разделе Построение приложения WPF представлены дополнительные сведения о том, как построить включающие XAML приложения из командной строки и в Microsoft Visual Studio.

В Общие сведения о свойствах зависимости представлены дополнительные сведения о разнообразии свойств в WPF и описано понятие свойств зависимости.

См. также

Основные понятия

Подробное описание синтаксиса XAML

Код XAML и пользовательские классы для WPF

Общие сведения о базовых элементах

Деревья в WPF

Другие ресурсы

Возможности пространства имен языка XAML (x:)

Расширения XAML WPF