Заметка
Доступ к этой странице требует авторизации. Вы можете попробовать войти в систему или изменить каталог.
Доступ к этой странице требует авторизации. Вы можете попробовать сменить директорию.
В этом разделе определяются термины, используемые для описания элементов синтаксиса XAML. Эти термины часто используются в остальной части этой документации, как для документации WPF, так и для других платформ, использующих XAML или основные понятия XAML, включенные поддержкой языка XAML на уровне System.Xaml. В этом разделе рассматриваются основные термины, представленные в разделе XAML в WPF.
Спецификация языка XAML
Терминология синтаксиса XAML, определенная здесь, также определяется или ссылается в спецификации языка XAML. XAML — это язык, основанный на XML, который следует структурным правилам XML или расширяет их. Некоторые термины используются или основаны на терминологии, обычно используемой при описании языка XML или объектной модели XML-документа.
Дополнительные сведения о спецификации языка XAML скачайте [MS-XAML] из Центра загрузки Майкрософт.
XAML и CLR
XAML — это язык разметки. Универсальная среда выполнения (CLR), как подразумевается ее названием, позволяет выполнение в среде выполнения. XAML не является одним из языков программирования, которые напрямую используются средой CLR. Вместо этого можно подумать о XAML как о поддержке собственной системы типов. Конкретная система синтаксического анализа XAML, используемая WPF, основана на среде CLR и системе типов CLR. Типы XAML сопоставляются с типами CLR для создания представления во время выполнения при разборе XAML для WPF. По этой причине оставшиеся обсуждения синтаксиса в этом документе будут включать ссылки на систему типов CLR, несмотря на то что эквивалентные обсуждения синтаксиса в спецификации языка XAML не включают их. (На уровне спецификации языка XAML типы XAML можно сопоставить с любой другой системой типов, которая не должна быть средой CLR, но требует создания и использования другого средства синтаксического анализа XAML.)
Члены типов и наследование классов
Свойства и события, отображаемые как элементы XAML типа WPF, часто наследуются от базовых типов. Например, рассмотрим этот пример: <Button Background="Blue" .../> Свойство Background не является немедленно объявленным свойством класса Button , если вы хотите просмотреть определение класса, результаты отражения или документацию. Вместо этого наследуется Background от базового Control класса.
Поведение наследования классов элементов XAML WPF является значительным отклонением от интерпретации разметки XML, применяемой схемой. Наследование классов может стать сложным, особенно если промежуточные базовые классы являются абстрактными или когда используются интерфейсы. Это одна из причин, по которой набор элементов XAML и их допустимые атрибуты трудно представить точно и полностью с помощью типов схем, которые обычно используются для xml-программирования, таких как формат DTD или XSD. Другая причина заключается в том, что возможности расширяемости и сопоставления типов самого языка XAML препятствуют полноте любого фиксированного представления допустимых типов и элементов.
Синтаксис элемента object
Синтаксис элемента объекта — это синтаксис разметки XAML, создающий экземпляр класса или структуры СРЕДЫ CLR путем объявления XML-элемента. Этот синтаксис напоминает синтаксис элементов других языков разметки, таких как HTML. Синтаксис элемента объекта начинается с левой угловой скобки (<), за которым следует сразу же имя типа класса или структуры. Ноль или больше пробелов могут следовать за названием типа, а также может быть объявлено ноль или больше атрибутов на объектном элементе, при этом каждый набор атрибутов "имя=значение" разделяется одним или несколькими пробелами. Наконец, одно из следующих утверждений должно быть верным:
Элемент и тег должны быть закрыты слэшем (/), за которым следует правая угловая скобка (>).
Открывающий тег должен быть завершен правой угловой скобкой (>). Другие элементы объекта, элементы свойств или внутренний текст могут следовать открываемой тегу. Именно то, что содержимое может содержаться здесь, обычно ограничивается объектной моделью элемента. Эквивалентный закрывающий тег для элемента объекта также должен существовать, правильно вложенный и сбалансированный с другими парами открывающих и закрывающих тегов.
XAML, реализованный в .NET, имеет набор правил, которые сопоставляют элементы объекта с типами, атрибуты — со свойствами или событиями, а пространства имен XAML — с пространствами имен CLR и сборками. Для WPF и .NET элементы объекта XAML сопоставляются с типами .NET, определенными в ссылочных сборках, и атрибуты сопоставляются с элементами этих типов. При ссылке на тип CLR в XAML у вас также есть доступ к унаследованным элементам этого типа.
Например, следующий пример — синтаксис элемента объекта, который создает экземпляр нового экземпляра Button класса, а также задает Name атрибут и значение для этого атрибута:
<Button Name="CheckoutButton"/>
В следующем примере приведен синтаксис элемента объекта, который также включает синтаксис свойства содержимого XAML. Внутренний текст будет использоваться для установки свойства содержимого XAML TextBox. Text
<TextBox>This is a Text Box</TextBox>
Модели содержимого
Класс может поддерживать использование в качестве элемента объекта XAML с точки зрения синтаксиса, но этот элемент будет работать правильно в приложении или странице, когда он помещается в ожидаемое положение общей модели содержимого или дерева элементов. Например, MenuItem обычно должно быть помещено в качестве дочернего элемента производного класса MenuBase, такого как Menu. Модели содержимого для определенных элементов документируются как часть примечаний на страницах классов для элементов управления и других классов WPF, которые можно использовать в качестве элементов XAML.
Свойства элементов объекта
Свойства в XAML задаются различными возможными синтаксисами. Какой синтаксис можно использовать для определенного свойства, зависит от характеристик базовой системы типов заданного свойства.
Задав значения свойств, вы добавляете функции или характеристики к объектам, как они существуют в графе объектов времени выполнения. Начальное состояние созданного объекта из элемента объекта основано на поведении конструктора без параметров. Как правило, приложение будет использовать что-то, отличное от полного экземпляра по умолчанию любого заданного объекта.
Синтаксис атрибутов (свойства)
Синтаксис атрибута — это синтаксис разметки XAML, который задает значение для свойства путем объявления атрибута в существующем элементе объекта. Имя атрибута должно совпадать с именем члена свойства класса, который поддерживает соответствующий объект элемента в CLR. За именем атрибута следует оператор назначения (=). Значение атрибута должно быть строкой, заключенной в кавычки.
Замечание
С помощью чередующихся кавычек можно поместить символ кавычки в атрибут. Например, одинарные кавычки можно использовать как способ задания строки, содержащей символ двойного кавычки. Независимо от того, используете ли вы одинарные или двойные кавычки, следует использовать соответствующую пару для открытия и закрытия строки значения атрибута. Существуют также экранирующие последовательности или другие техники, доступные для обхода ограничений на символы, введенных любым синтаксисом XAML. См. сущности символов XML и XAML.
Для задания с помощью синтаксиса атрибута свойство должно быть общедоступным и должно быть записываемым. Значение свойства в системе типов данных должно быть значимым типом или ссылочным типом, который может быть создан или на который может ссылаться обработчик XAML при доступе к соответствующему резервному типу.
Для событий XAML WPF событие, на которое ссылается имя атрибута, должно быть публичным и иметь публичный делегат.
Свойство или событие должно быть членом класса или структуры, созданной содержащим элементом объекта.
Обработка значений атрибутов
Строковое значение, содержащееся в открывающих и закрывающих кавычках, обрабатывается обработчиком XAML. Для свойств поведение обработки по умолчанию определяется типом базового свойства CLR.
Значение атрибута заполняется одним из следующих значений, используя этот порядок обработки:
Если обработчик XAML встречает фигурную скобку или элемент объекта, производный от MarkupExtension, то расширение разметки, на которое ссылается, вычисляется сначала, а не обрабатывает значение в виде строки, а объект, возвращаемый расширением разметки, используется в качестве значения. Во многих случаях объект, возвращаемый расширением разметки, будет ссылкой на существующий объект или выражение, которое откладывает оценку до времени выполнения и не является вновь созданным объектом.
Если свойство объявляется с атрибутом или тип значения этого свойства объявляется с атрибутомTypeConverterTypeConverter, строковое значение атрибута передается преобразователю типов в качестве входных данных преобразования, а преобразователь вернет новый экземпляр объекта.
Если нет TypeConverter, предпринята попытка прямого преобразования в тип свойства. Этот окончательный уровень — это прямое преобразование на уровне синтаксического анализатора собственного значения примитивных типов языка XAML или проверка именованных констант в перечне (парсер обращается к нужным значениям).
Значения атрибутов перечисления
Перечисления в XAML обрабатываются встроенными средствами синтаксического анализа XAML, а элементы перечисления должны быть указаны путем указания имени строки одной из именованных констант перечисления.
Для значений перечисления, не являющихся флагами, собственное поведение заключается в обработке строки значения атрибута и его разрешении на одно из значений перечисления. Вы не указываете перечисление в формате Enumeration.Value, как это делаете в коде. Вместо этого указывается только значение, а перечисление определяется типом заданного свойства. Если в перечислении указан атрибут. Форма значений , она не будет разрешаться правильно.
Для перечислений на основе флагов поведение основано на методе Enum.Parse. Можно указать несколько значений для перечисления по флаговой стрелке, разделив каждое значение запятой. Однако нельзя объединить значения перечисления, которые не являются флагами. Например, нельзя использовать синтаксис запятой для создания объекта Trigger, который действует по нескольким условиям нефлагового перечисления.
<!--This will not compile, because Visibility is not a flagwise enumeration.-->
...
<Trigger Property="Visibility" Value="Collapsed,Hidden">
<Setter ... />
</Trigger>
...
Флаговые перечисления, поддерживающие атрибуты, которые можно задать в XAML, встречаются редко в WPF. Однако одно из таких перечислений — это StyleSimulations. Например, можно использовать синтаксис атрибута с разделителями-запятыми, чтобы изменить пример, приведенный в примечаниях для Glyphs класса; StyleSimulations = "BoldSimulation" может стать StyleSimulations = "BoldSimulation,ItalicSimulation".
KeyBinding.Modifiers — другое свойство, где можно указать несколько значений перечисления. Однако это свойство может быть особым случаем, так как ModifierKeys перечисление поддерживает собственный преобразователь типов. Преобразователь типов для модификаторов использует знак плюса (+) в качестве разделителя, а не запятой (,). Это преобразование поддерживает более традиционный синтаксис для представления сочетаний клавиш в программировании Microsoft Windows, таких как CTRL+ALT.
Ссылки на свойства и имя члена события
При указании атрибута можно ссылаться на любое свойство или событие, существующее в качестве члена типа CLR, созданного для содержащего элемента объекта.
Кроме того, можно ссылаться на присоединенное свойство или присоединенное событие независимо от содержащего элемента объекта. (Присоединенные свойства рассматриваются в предстоящем разделе.)
Можно также назвать любое событие из любого объекта, доступного через пространство имен по умолчанию, с помощью typeName.event частично квалифицированного имени; этот синтаксис поддерживает присоединение обработчиков для маршрутизируемых событий, в которых обработчик предназначен для обработки маршрутизации событий из дочерних элементов, но родительский элемент не имеет этого события в таблице членов. Этот синтаксис напоминает синтаксис присоединенного события, но событие здесь не является истинным присоединенным событием. Вместо этого вы ссылаетесь на событие с квалифицированным именем. Дополнительные сведения см. в обзоре маршрутизируемых событий.
В некоторых сценариях имена свойств иногда предоставляются в качестве значения атрибута, а не имени атрибута. Это имя свойства также может включать квалификаторы, такие как свойство, указанное в форме типВладельца.имяЗависимогоСвойства. Этот сценарий распространен при написании стилей или шаблонов в XAML. Правила обработки имен свойств, предоставленные в качестве значения атрибута, отличаются и управляются типом устанавливаемого свойства или поведением определенных подсистем WPF. Дополнительные сведения см. в разделе "Стилизация" и "Шаблон".
Другое использование имен свойств заключается в том, когда значение атрибута описывает отношение между свойствами. Эта функция используется для привязки данных и для целевых объектов раскадровки и включается классом PropertyPath и его преобразователем типов. Более полное описание семантики поиска см. в Синтаксис XAML PropertyPath.
Синтаксис элемента property
Синтаксис элемента свойства — это синтаксис, который несколько отличается от основных правил синтаксиса XML для элементов. В XML значение атрибута является де-факто строкой, а единственным возможным вариантом является используемый формат кодировки строк. В XAML можно назначить другие элементы объекта значением свойства. Эта возможность включена синтаксисом элемента свойства. Вместо того, чтобы свойство указывать в качестве атрибута внутри тега элемента, оно указывается с помощью открывающего тега элемента в форме elementTypeName.propertyName, затем указывается его значение, и элемент свойства закрывается.
В частности, синтаксис начинается с левой угловой скобки (<), за которым следует сразу же имя типа класса или структуры, в которой содержится синтаксис элемента свойства. За этим следует сразу одна точка (.), а затем по имени свойства, а затем правой угловой скобкой (>). Как и синтаксис атрибута, это свойство должно существовать в объявленных открытых членах указанного типа. Значение, назначенное свойству, содержится в элементе свойства. Как правило, значение задается как один или несколько объектов, потому что указание объектов в качестве значений является сценарием, который синтаксис элемента свойства предназначен для решения. Наконец, должен быть предоставлен эквивалентный закрывающий тег, задающий ту же комбинацию элементTypeName и propertyName, с правильным вложением и балансом с другими тегами элементов.
Например, ниже приведен синтаксис элемента свойства для ContextMenu свойства Button объекта.
<Button>
<Button.ContextMenu>
<ContextMenu>
<MenuItem Header="1">First item</MenuItem>
<MenuItem Header="2">Second item</MenuItem>
</ContextMenu>
</Button.ContextMenu>
Right-click me!</Button>
Значение в элементе свойства также может быть задано как текстовое содержимое, в случаях, когда указанный тип свойства является примитивным типом значения, например, String, или перечислением, где указано имя. Эти два использования несколько редки, так как каждый из этих вариантов также может использовать более простой синтаксис атрибута. Один из сценариев заполнения элемента свойства строкой — это свойства, которые не являются свойством содержимого XAML, но по-прежнему используются для представления текста пользовательского интерфейса, а для отображения в этом тексте пользовательского интерфейса требуются определенные элементы пробела, такие как линии. Синтаксис атрибутов не может сохранять переводы строк, но синтаксис элементов свойств может, если включено сохранение значительных пробелов (подробности см. в разделе "Обработка пробелов в XAML). Другой сценарий заключается в том, что директива x:Uid может быть применена к элементу свойства, чтобы пометить значение внутри как значение, которое должно быть локализовано в выходных BAML-файлах WPF или другими методами.
Элемент свойства не представлен в логическом дереве WPF. Элемент свойства — это просто определенный синтаксис для задания свойства и не является элементом, который имеет экземпляр или объект, который его поддерживает. (Дополнительные сведения о концепции логического дерева см. в разделе "Деревья" в WPF.)
Для свойств, где поддерживаются синтаксис атрибута и элемента свойства, два синтаксиса обычно имеют одинаковый результат, хотя тонкости, такие как обработка пробелов, могут немного отличаться между синтаксисами.
Синтаксис коллекции
Спецификация XAML требует реализации обработчика XAML для определения свойств, в которых тип значения является коллекцией. Общая реализация обработчика XAML в .NET основана на управляемом коде и среде CLR и определяет типы коллекций с помощью одного из следующих типов:
Тип реализует IList.
Тип реализует IDictionary.
Тип является производным от Array (дополнительные сведения о массивах в XAML см. в разделе x:Array Markup Extension.)
Если тип свойства является коллекцией, то выводимого типа коллекции не требуется указывать в разметке как элемент объекта. Вместо этого элементы, предназначенные для создания элементов в коллекции, указываются как один или несколько дочерних элементов элемента свойства. Каждый такой элемент оценивается как объект во время загрузки и добавляется в коллекцию путем вызова Add метода подразумеваемой коллекции. Например, свойство Triggers коллекции Style принимает специализированный тип TriggerCollection, который реализует IList. В разметке не обязательно создавать экземпляр элемента объекта TriggerCollection. Вместо этого вы указываете один или несколько Trigger элементов как части элемента свойства Style.Triggers, где Trigger (или производный класс) представляет собой тип, ожидаемый как тип элемента для строго типизированного и неявного TriggerCollection.
<Style x:Key="SpecialButton" TargetType="{x:Type Button}">
<Style.Triggers>
<Trigger Property="Button.IsMouseOver" Value="true">
<Setter Property = "Background" Value="Red"/>
</Trigger>
<Trigger Property="Button.IsPressed" Value="true">
<Setter Property = "Foreground" Value="Green"/>
</Trigger>
</Style.Triggers>
</Style>
Свойство может быть как типом коллекции, так и свойством содержимого XAML для этого типа и производных типов, которые рассматриваются в следующем разделе этого раздела.
Неявный элемент коллекции создает элемент в логическом представлении дерева, даже если он не отображается в разметке как элемент. Обычно конструктор родительского типа выполняет создание экземпляра коллекции, которая является одним из его свойств, и коллекция, которая изначально пуста, становится частью дерева объектов.
Замечание
Универсальные интерфейсы списков и словарей (IList<T> и IDictionary<TKey,TValue>) не поддерживаются для обнаружения коллекции. Однако класс List<T> можно использовать как базовый класс, так как он реализует IList напрямую или Dictionary<TKey,TValue> в качестве базового класса, так как он реализует IDictionary напрямую.
На страницах справочника .NET для типов коллекций иногда отмечается синтаксис, в котором преднамеренно опускается элемент-объект коллекции, в разделах синтаксиса XAML он называется синтаксисом неявной коллекции.
За исключением корневого элемента, каждый элемент объекта в XAML-файле, вложенный как дочерний элемент другого элемента, действительно является элементом, который является одним или обоими из следующих случаев: членом неявного свойства коллекции его родительского элемента или элементом, указывающим значение свойства содержимого XAML для родительского элемента (свойства содержимого XAML будут рассмотрены в следующем разделе). Другими словами, связь родительских элементов и дочерних элементов на странице разметки действительно является одним объектом в корне, и каждый элемент объекта под корнем является одним экземпляром, который предоставляет значение свойства родительского элемента или один из элементов в коллекции, которая также является значением свойства типа коллекции родительского элемента. Эта концепция с одним корнем распространена в XML, а также часто поддерживается в работе API, загружающих XAML, например Load.
В следующем примере используется синтаксис с элементом объекта для коллекции (GradientStopCollection), заданным явным образом.
<LinearGradientBrush>
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Offset="0.0" Color="Red" />
<GradientStop Offset="1.0" Color="Blue" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
Обратите внимание, что невозможно явно объявить коллекцию. Например, попытка явно объявить TriggerCollection в приведенном выше Triggers примере завершится ошибкой. Явно объявляя коллекцию, требуется, чтобы класс коллекции поддерживал конструктор без параметров и TriggerCollection не имеет конструктора без параметров.
Свойства содержимого XAML
Синтаксис содержимого XAML — это синтаксис, который включен только в классах, которые указывают ContentPropertyAttribute как часть объявления класса. Элемент ContentPropertyAttribute относится к имени свойства, которое служит свойством содержимого для этого типа элемента (включая производные классы). При обработке обработчиком XAML все дочерние элементы или внутренний текст, найденные между открывающим и закрывающим тегами элемента объекта, будут назначены значение свойства содержимого XAML для этого объекта. Вы можете указать явные элементы свойств для свойства содержимого, но это использование обычно не отображается в разделах синтаксиса XAML в справочнике по .NET. Явный или подробный метод иногда может быть полезен для ясности разметки или как вопрос стиля разметки, но обычно намерение свойства контента заключается в упрощении разметки так, чтобы элементы, интуитивно связанные друг с другом как родитель и ребенок, могли быть вложены напрямую. Теги элементов свойства для других свойств элемента не назначаются как "содержимое" для строгого определения языка XAML; они обрабатываются ранее в порядке обработки средства синтаксического анализа XAML и не считаются "контентом".
Значения свойств содержимого 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 должен определять типы, которые являются типами коллекций. Если элемент имеет свойство содержимого XAML и тип свойства содержимого XAML является коллекцией, то подразумеваемый тип коллекции не должен быть указан в разметке в качестве элемента объекта, а свойство содержимого XAML не должно быть указано в качестве элемента свойства. Поэтому видимая модель содержимого в разметке теперь может иметь несколько дочерних элементов, назначенных в качестве содержимого. Ниже приведен синтаксис содержимого для производного Panel класса. Все Panel производные классы устанавливают свойство Children содержимого XAML, которое требует значения типа UIElementCollection.
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
<StackPanel>
<Button>Button 1</Button>
<Button>Button 2</Button>
<Button>Button 3</Button>
</StackPanel>
</Page>
Обратите внимание, что в разметке не требуется ни элемент свойства для Children, ни элемент для UIElementCollection. Это функция конструктора XAML, поэтому рекурсивно содержащиеся элементы, определяющие пользовательский интерфейс, более интуитивно представлены в виде дерева вложенных элементов с непосредственными связями элементов с родительским дочерним элементом без взаимодействия тегов элементов свойств или объектов коллекции. На самом деле UIElementCollection не может быть явно указан в разметке как элемент объекта по замыслу. Поскольку его единственное предполагаемое использование является неявной коллекцией, UIElementCollection не предоставляет открытый конструктор без параметров и поэтому не может быть создан в качестве элемента объекта.
Сочетание элементов свойств и элементов объекта в объекте с контентным свойством
Спецификация XAML указывает, что обработчик XAML может обеспечить, чтобы объектные элементы, используемые для заполнения свойства содержимого XAML в элементе объекта, были смежными и не смешивались с другими. Это ограничение против смешивания элементов свойств и содержимого обеспечивается процессорами WPF XAML.
Дочерний элемент объекта можно использовать как первую немедленную разметку в элементе объекта. Затем можно ввести элементы свойств. Кроме того, можно указать один или несколько элементов свойства, а затем содержимое, а затем несколько элементов свойства. Но когда элемент свойства следует содержимому, вы не можете ввести дополнительное содержимое, можно добавлять только элементы свойств.
Это требование к порядку элементов содержимого или свойства не применяется к внутреннему тексту, используемому в качестве содержимого. Тем не менее, это по-прежнему хороший стиль разметки, чтобы сохранить внутренний текст непрерывным, так как значительные пробелы будет трудно обнаружить визуально в разметке, если элементы свойств перемежаются с внутренним текстом.
Пространства имен XAML
Ни один из предыдущих примеров синтаксиса не указал пространство имен XAML, отличное от пространства имен XAML по умолчанию. В типичных приложениях WPF пространство имен XAML по умолчанию указывается как пространство имен WPF. Можно указать пространства имен XAML, отличные от пространства имен XAML по умолчанию, и использовать аналогичный синтаксис. Но в любом месте, где задается имя класса, недоступного в пространстве имен XAML по умолчанию, имени класса должен предшествовать префикс пространства имен XAML, сопоставленного с соответствующим пространством имен CLR. Например, <custom:Example/> синтаксис элемента объекта для создания экземпляра класса, в котором пространство имен CLR, содержащее этот класс (и, возможно, данные внешней сборки, содержащие типы резервного Example копирования), ранее сопоставлены с custom префиксом.
Дополнительные сведения о пространствах имен XAML см. в разделе "Пространства имен XAML" и "Сопоставление пространств имен" для WPF XAML.
Расширения разметки
XAML определяет сущность программирования расширения разметки, которая обеспечивает выход из обычной обработки обработчика XAML значений строковых атрибутов или элементов объекта, а также откладывает обработку в резервный класс. Символ, определяющий расширение разметки для обработчика XAML при использовании синтаксиса атрибутов, представляет собой открывающую фигурную скобку ({), за которой следует любой символ, отличный от закрывающей фигурной скобки (}). Первая строка после открывающей фигурной скобки должна ссылаться на класс, предоставляющий определенное поведение расширения, где ссылка может опустить подстроку Extension, если эта подстрока является частью имени истинного класса. После этого может появиться один пробел, а затем каждый следующий символ используется как вход расширением до тех пор, пока не будет обнаружена закрывающая фигурная скобка.
Реализация XAML .NET использует абстрактный MarkupExtension класс в качестве основы для всех расширений разметки, поддерживаемых WPF, а также других платформ или технологий. Расширения разметки, которые в частности реализует WPF, часто предназначены для предоставления средств для ссылки на другие существующие объекты или для отложенных ссылок на объекты, которые будут оцениваться во время выполнения. Например, простая привязка данных WPF выполняется путем указания {Binding} расширения разметки вместо значения, которое определенное свойство обычно принимает. Многие расширения разметки WPF позволяют использовать синтаксис атрибута для свойств, где он иначе был бы невозможен. Например, Style объект является относительно сложным типом, который содержит вложенный ряд объектов и свойств. Стили в WPF обычно определяются как ресурс в объекте ResourceDictionary, а затем ссылаются на один из двух расширений разметки WPF, запрашивающих ресурс. Расширение разметки откладывает оценку значения свойства до поиска ресурсов и позволяет использовать значение Style свойства, принимая тип Style в синтаксисе атрибута, как показано в следующем примере:
<Button Style="{StaticResource MyStyle}">My button</Button>
Здесь StaticResource идентифицирует StaticResourceExtension класс, предоставляющий реализацию расширения разметки. Следующая строка MyStyle используется в качестве входных данных для нестандартного конструктора StaticResourceExtension, где параметр, полученный из строки расширения, определяет запрошенный ResourceKey.
MyStyle ожидается как значение x:Key для Style, определённого как ресурс. Использование расширения разметки StaticResource требует, чтобы ресурс предоставил значение свойства через логику подстановки статических ресурсов во время загрузки.
Дополнительные сведения о расширениях разметки см. в расширения разметки иWPF XAML. Справочник по расширениям разметки и другим функциям программирования XAML, включенным в общей реализации XAML .NET, см. в разделе "Функции языка пространства имен XAML (x:). Расширения разметки для WPF см. в разделе "Расширения XAML WPF".
Присоединенные свойства
Присоединенные свойства — это концепция программирования, представленная в XAML, где свойства могут принадлежать и определяться определенным типом, но задавать как атрибуты или элементы свойств для любого элемента. Основной сценарий, для которого присоединенные свойства предназначены, заключается в том, чтобы дочерние элементы в структуре разметки сообщали сведения родительскому элементу, не требуя обширной общей объектной модели для всех элементов. И наоборот, присоединенные свойства можно использовать родительскими элементами для отправки сведений дочерним элементам. Дополнительные сведения о назначении присоединенных свойств и создании собственных присоединенных свойств см. в разделе "Общие сведения о присоединенных свойствах".
Присоединенные свойства используют синтаксис, который внешне напоминает синтаксис элемента свойства, так как также указывается сочетание typeName.propertyName. Существует два важных различия:
Вы можете использовать комбинацию typeName.propertyName даже при установке присоединенного свойства через синтаксис атрибута. Присоединенные свойства являются единственным случаем, когда определение имени свойства является требованием в синтаксисе атрибута.
Вы также можете использовать синтаксис элемента свойства для присоединенных свойств. Однако для типичного синтаксиса элемента свойств указанный typeName является объектным элементом, который содержит элемент свойства. Если вы ссылаетесь на присоединенное свойство, typeName — это класс, который определяет присоединенное свойство, а не содержащий элемент объекта.
Присоединенные события
Присоединенные события — это другая концепция программирования, представленная в XAML, где события могут быть определены определенным типом, но обработчики могут быть присоединены к любому элементу объекта. В реализации WOF тип, который часто определяет присоединенное событие, является статическим типом, определяющим службу. Иногда такие присоединенные события представлены в виде псевдонима маршрутизируемого события в типах, которые предоставляют эту службу. Обработчики присоединенных событий задаются с помощью синтаксиса атрибута. Как и в случае с присоединяемыми событиями, синтаксис атрибута расширен для использования конструкции typeName.eventName, где typeName — это класс, который предоставляет доступ к обработчикам событий Add и Remove для инфраструктуры присоединяемых событий, а eventName — это имя события.
Анатомия корневого элемента XAML
В следующей таблице показан типичный корневой элемент XAML с разбивкой на определенные атрибуты корневого элемента:
| Свойство | Описание |
|---|---|
<Page |
Открытие элемента объекта корневого элемента |
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
Пространство имен XAML по умолчанию (WPF) |
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
Пространство имен XAML языка XAML |
x:Class="ExampleNamespace.ExampleCode" |
Объявление частичного класса, которое связывает разметку с любым кодом, находящимся за разметкой и определенным для частичного класса |
> |
Конец элемента объекта для корневого элемента. Объект еще не закрыт, так как элемент содержит дочерние элементы |
Необязательные и нерекомендуемые использование XAML
В следующих разделах описывается использование XAML, которые технически поддерживаются процессорами XAML, но создают подробные сведения или другие эстетические проблемы, которые влияют на использование файлов XAML, оставшихся доступными для чтения при разработке приложений, содержащих источники XAML.
Использование необязательных элементов свойств
Необязательное использование элементов свойств включает явное указание свойств содержимого элемента, которые обработчик XAML считает неявными. Например, когда вы объявляете содержимое Menu, вы можете выбрать явное объявление коллекции Items из Menu как элемента свойства <Menu.Items>, и разместить каждый MenuItem внутри <Menu.Items>, вместо использования неявного поведения процессора XAML, предполагающего, что все дочерние элементы Menu должны быть MenuItem и помещаться в коллекцию Items. Иногда необязательные использования могут помочь визуально уточнить структуру объекта, представленную в разметке. Или иногда явное использование элемента свойства может избежать разметки, которая является технически функциональной, но визуально запутанной, например вложенных расширений разметки в значении атрибута.
Полные атрибуты typeName.memberName
Форма typeName.memberName для атрибута фактически работает более универсально, чем только в случае маршрутизированного события. Но в других ситуациях, где форма является излишней, вы должны избегать ее, если только по причинам разметки и удобочитаемости. В следующем примере каждая из трех ссылок на Background атрибут полностью эквивалентна:
<Button Background="Blue">Background</Button>
<Button Button.Background="Blue">Button.Background</Button>
<Button Control.Background="Blue">Control.Background</Button>
Button.Background работает, так как квалифицированный поиск этого свойства Button успешноBackground (наследуется от Control) и Button является классом элемента объекта или базового класса.
Control.Background работает, так как Control класс фактически определяет Background и Control является базовым классом Button .
Однако следующее имя типа. Пример формы memberName не работает и поэтому отображается примечания:
<!--<Button Label.Background="Blue">Does not work</Button> -->
Label является другим производным классом Control, и если бы вы указали Label.Background в элементе Label объекта, это использование работало бы. Тем не менее, так как Label не является классом или базовым классом Button, указанное поведение процессора XAML будет обрабатываться Label.Background как присоединенное свойство.
Label.Background не является доступным присоединенным свойством, и это использование приводит к ошибке.
Элементы свойства baseTypeName.memberName
Аналогично тому, как синтаксис typeName.memberName используется для атрибутов, синтаксис baseTypeName.memberName применяется для элементов свойств. Например, следующий синтаксис работает:
<Button>Control.Background PE
<Control.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
<GradientStop Color="Yellow" Offset="0.0" />
<GradientStop Color="LimeGreen" Offset="1.0" />
</LinearGradientBrush>
</Control.Background>
</Button>
Здесь элемент свойства был задан Control.Background , хотя элемент свойства был содержится в Button.
Так же, как форма typeName.memberName для атрибутов, использование baseTypeName.memberName является плохим стилем в разметке, и его следует избегать.
См. также
.NET Desktop feedback