Обзор XAML (WPF)
В этом разделе описаны возможности языка XAML и показано, как использовать язык XAML для написания приложений Windows Presentation Foundation (WPF). В частности, в этом разделе описывается реализация XAML в WPF. Сам язык XAML — это более широкое понятие языка, чем WPF.
Что это такое язык 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 указывает свойство content от 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="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="ExampleNamespace.ExamplePage">
<Button Click="Button_Click" >Click Me!</Button>
</Page>
Помимо этого примера синтаксиса атрибутов, имеется больше информации по событиям и XAML в WPF. Например, может возникнуть вопрос, что представляет и как определяется указанный здесь атрибут ClickHandler
. Ответ можно найти в следующем подразделе События и код программной части XAML этого раздела.
Регистр и пробелы в 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 и более доступных для реализаций .NET Framework XAML, см. в разделе пространства имен XAML (x:) Возможности языка. Дополнительные сведения о понятиях расширений разметки см. в разделе Расширения разметки и XAML WPF.
Преобразователи типов
В разделе Краткое описание синтаксиса XAML было отмечено, что необходимо обеспечить возможность задать значение атрибута строкой. Основная собственная обработка преобразования строк в другие типы объектов или простые значения основана на 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>
Note
Кроме того, существует ограниченное количество объектов, для которых преобразование типов является единственным открытым способом присвоения свойству значения нужного типа без использования подкласса, так как у самого типа отсутствует конструктор по умолчанию. Например, Cursor.
Дополнительные сведения о поддержке преобразователя типов для синтаксиса атрибутов см. в разделе TypeConverters и XAML.
Корневые элементы XAML и пространства имен XAML
Файл XAML должен иметь только один корневой элемент, чтобы одновременно быть файлом XML с правильным форматом и допустимым файлом XAML. В скриптах WPF используется корневой элемент, имеющий значимый в модели приложения WPF (например, Window или Page для страницы, ResourceDictionary для внешнего словаря или Application для определения приложения). В следующем примере показано корневой элемент обычного файла XAML для WPF страницы с корневым элементом Page.
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
</Page>
Корневой элемент также содержит атрибуты xmlns
и xmlns:x
. Эти атрибуты указывают обработчику XAML, какие пространства имен XAML содержат определения типов для резервных типов, на которые будет ссылаться разметка в качестве элементов. Атрибут xmlns
специально указывает пространство имен XAML по умолчанию. В пределах пространства имен XAML по умолчанию объектные элементы в разметке можно указывать без префикса. Для большинства сценариев приложения WPF и практически для всех примеров, приведенных в разделах WPF SDK, пространство имен XAML по умолчанию сопоставлено с пространством имен WPF http://schemas.microsoft.com/winfx/2006/xaml/presentation. Атрибут xmlns:x
указывает дополнительное пространство имен XAML, которое сопоставлено пространству имен языка http://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 http://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 при эквивалентных уровня среды WPF Name свойство не поддерживается в определенного типа. Это происходит в некоторых сценариях анимации.
x: Static: Позволяет использовать ссылку, возвращающую статическое значение, которое не может быть свойством, совместимым с XAML.
x: Type: Создает Type ссылку на основании имени типа. Это используется для указания атрибутов, которые принимают Type, такие как Style.TargetType, хотя часто свойство имеет собственную строку-к-Type преобразование таким образом, x: Type является использование расширения разметки необязательно.
Существуют дополнительные конструкции программирования в пространстве имен XAML/с префиксом x:
, которые применяются не так часто. Дополнительные сведения см. в разделе пространства имен XAML (x:) Возможности языка.
Пользовательские префиксы и пользовательские типы в XAML
При использовании собственных пользовательских сборок или сборок PresentationCore, PresentationFramework и WindowsBase за пределами ядра WPF можно указать сборку как часть пользовательского сопоставления xmlns
. Затем можно указывать в пользовательском XAML-коде ссылки на типы из этой сборки, если в типе правильно реализована поддержка требуемых средств XAML.
Ниже приведен очень общий пример работы пользовательских префиксов в разметке XAML. Префикс custom
определен в теге корневого элемента и сопоставляется с конкретной сборкой, упакованной и доступной в приложении. Эта сборка содержит тип NumericUpDown
, который реализуется для поддержки общего использования XAML, а также использования наследования класса, которое можно вставить в данную конкретную точку модели содержимого XAML WPF. Экземпляр этого элемента управления NumericUpDown
объявлен как объектный элемент, префикс обеспечивает, что анализатор XAML "знает", какое пространство имен XAML содержит тип и, следовательно, где находится резервная сборка, содержащая определение типа.
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://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="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="ExampleNamespace.ExamplePage">
<Button Click="Button_Click" >Click Me!</Button>
</Page>
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>
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, поддерживает элементы, ориентированные на документы, которые работают для представления макета потока, используя API , намеренно дублирующие API в FrameworkElement. Сочетание атрибутов на уровне элементов и объектной модели CLR обеспечивает набор общих свойств, которые можно задать для большинства конкретных элементов XAML, независимо от типа элемента XAML и его базового типа.
Безопасность XAML
XAML — это язык разметки, непосредственно представляющий создание и выполнение объекта. Таким образом, элементы, созданные в XAML, имеют такие же возможности взаимодействия с системными ресурсами (например, сетевой доступ и операции ввода-вывода файловой системы), как и эквивалентный созданный код.
WPF поддерживает .NET Framework 4 платформа безопасности CAS (Code Access Security — безопасность доступа кода). Это означает, что содержимое WPF, работающее в зоне Интернет, сократило разрешения исполнения. "Свободный XAML" (страницы некомпилированного XAML, интерпретируемые во время загрузки средства просмотра XAML) и Приложение обозревателя XAML (XBAP) обычно выполняются в этой Интернет-зоне и используют один набор разрешений. Однако XAML, загруженный в полностью доверенное приложение, имеет такой же доступ к системным ресурсам, как ведущее приложение. Дополнительные сведения см. в разделе Безопасность частичного доверия в WPF.
Загрузка XAML из кода
XAML можно использовать для определения всего пользовательского интерфейса, но иногда также уместно определение в XAML только его части. Эта возможность может использоваться для включения частичной настройки, локального хранения данных, использования XAML для предоставления бизнес-объекта или различных возможных сценариев. Эти сценарии лежат XamlReader класса и его Load метод. Входные данные являются файлом XAML, а выходные данные — объектом, представляющим дерево объектов времени выполнения, созданных по разметке. Затем можно вставить объект, который будет свойством другого объекта, уже существующего в приложении. Пока свойство является допустимым свойством в модели содержимого, которая имеет возможности отображения и которая уведомляет ядро выполнения о добавлении в приложение нового содержимого, можно достаточно легко изменить содержимое работающего приложения путем загрузки XAML. Обратите внимание, что эта возможность доступна только в приложениях с уровнем полного доверия из-за очевидных с точки зрения безопасности последствий загрузки файлов в работающие приложения.
Дальнейшие действия
Этот раздел содержит основные сведения о терминологии и понятиях синтаксиса XAML применительно к WPF. Дополнительные сведения об используемых здесь терминах см. в разделе Подробное описание синтаксиса XAML.
Если вы еще не сделали это, выполните упражнения из раздела руководства Пошаговое руководство: Создание первого классического приложения WPF. При создании приложения, ориентированного на разметку и описанного в руководстве, упражнения помогут лучше осознать многие понятия, описанные в этом разделе.
WPF использует конкретную модель приложения, основанный на Application класса. Дополнительные сведения см. в разделе Общие сведения об управлении приложением.
В разделе Построение приложения WPF представлены дополнительные сведения о том, как построить включающие XAML приложения из командной строки и в Microsoft Visual Studio.
В разделе Общие сведения о свойствах зависимостей представлены дополнительные сведения о разнообразии свойств WPF и описано понятие свойств зависимостей.