Поделиться через


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

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

Процессоры XAML и расширения разметки

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

Базовый синтаксис расширения разметки

Расширение разметки можно реализовать для предоставления значений свойств в использовании атрибутов, свойств в использовании элемента свойства или обоих.

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

При использовании в синтаксисе элемента свойства расширение разметки выглядит как любой другой элемент, используемый для задания значения элемента свойства: объявление элемента XAML, которое ссылается на класс расширения разметки в виде элемента, заключённого в угловые скобки (<>).

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

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

  • x:Type предоставляет объект Type для именованного типа. Это средство чаще всего используется в стилях и шаблонах. Дополнительные сведения см. в разделе x:Type Markup Extension.

  • x:Static создает статические значения. Значения приходят из сущностей кода типа значений, которые не являются непосредственно типом значения целевого свойства, но могут быть оценены по такому типу. Дополнительные сведения см. в разделе x:Static Markup Extension.

  • x:Null указывает null значение свойства и может использоваться либо для атрибутов, либо для значений элементов свойства. Дополнительные сведения см. в разделе x:Null Markup Extension.

  • x:Array обеспечивает поддержку создания общих массивов в синтаксисе XAML, если поддержка коллекции, предоставляемая базовыми элементами WPF и моделями управления, намеренно не используется. Дополнительные сведения см. в разделе x:Array Markup Extension.

Замечание

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

расширения разметки WPF-Specific

Наиболее распространенные расширения разметки, используемые в программировании WPF, — это те, которые поддерживают ссылки на ресурсы (StaticResource и DynamicResource), а также те, которые поддерживают привязку данных (Binding).

  • StaticResource предоставляет значение для свойства, заменив значение уже определенного ресурса. Оценка StaticResource в конечном счете выполняется во время загрузки XAML и не имеет доступа к графу объектов во время выполнения. Дополнительные сведения см. в разделе "Расширение разметки StaticResource".

  • DynamicResource предоставляет значение для свойства, перенося его, чтобы оно стало ссылкой на ресурс во время выполнения. Динамическая ссылка на ресурсы создает новый поиск при каждом доступе к такому ресурсу и имеет доступ к графу объектов во время выполнения. Для получения этого доступа DynamicResource концепция поддерживается свойствами зависимостей в системе свойств WPF и вычисляемыми выражениями. Поэтому можно использовать DynamicResource только для целевого объекта свойства зависимостей. Дополнительные сведения см. в разделе Расширения разметки DynamicResource.

  • Binding предоставляет значение привязки данных для свойства, используя контекст данных, который применяется к родительскому объекту во время выполнения. Это расширение разметки является относительно сложным, так как он включает существенный встроенный синтаксис для указания привязки данных. Дополнительные сведения см. в разделе "Расширение разметки привязки".

  • RelativeSource предоставляет исходные сведения о Binding том, что может перемещаться по нескольким возможным связям в дереве объектов во время выполнения. Это обеспечивает специализированную выборку для привязок, созданных в многопользовательских шаблонах или созданных в коде без полного знания об окружающем дереве объектов. Дополнительные сведения см. в разделе RelativeSource MarkupExtension.

  • TemplateBinding позволяет шаблону элемента управления использовать значения для шаблонных свойств, поступающих из определяемых объектной моделью свойств класса, который будет использовать шаблон. Другими словами, свойство в определении шаблона может получить доступ к контексту, который существует только после применения шаблона. Дополнительные сведения см. в разделе "Расширение разметки TemplateBinding". Дополнительные сведения о практическом использовании TemplateBinding см. в примере Оформление с использованием ControlTemplates.

  • ColorConvertedBitmap поддерживает относительно расширенный сценарий визуализации. Дополнительные сведения см. в разделе ColorConvertedBitmap Markup Extension.

  • ComponentResourceKey и ThemeDictionary поддерживают функции поиска ресурсов, особенно для ресурсов и тем, которые поставляются с пользовательскими элементами управления. Дополнительные сведения см. в разделе "Расширение разметки ComponentResourceKey", расширение разметки ThemeDictionary или обзор разработки элементов управления.

*Классы расширений

Как для общего языка XAML, так и для расширений разметки WPF поведение каждого расширения разметки определяется обработчиком XAML через *Extension класс, производный от MarkupExtensionкласса, и предоставляет реализацию ProvideValue метода. Этот метод для каждого расширения предоставляет объект, возвращаемый при оценке расширения разметки. Возвращаемый объект обычно вычисляется на основе различных строковых маркеров, передаваемых в расширение разметки.

Например, класс StaticResourceExtension предоставляет базовую реализацию фактического поиска ресурсов так, чтобы реализация ProvideValue возвращала запрашиваемый объект. Входными данными для этой конкретной реализации является строка, которая используется для поиска ресурса по его x:Key. Большая часть этих сведений о реализации не является важной, если вы используете существующее расширение разметки.

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

Шаблон *Extension именования предназначен для удобства и согласованности. Обработчику XAML не требуется идентифицировать этот класс как поддержку расширения разметки. Если база кода включает в себя System.Xaml и использует реализации служб XAML в .NET Framework, все, что необходимо для распознавания в качестве расширения разметки XAML, — это наследоваться от MarkupExtension и поддерживать синтаксис построения. WPF определяет классы расширения разметки, которые не соответствуют шаблону именования *Extension, например Binding. Обычно это связано с тем, что класс поддерживает сценарии, кроме чистой поддержки расширения разметки. В случае Bindingэтого класса поддерживается доступ во время выполнения к методам и свойствам объекта для сценариев, которые не имеют ничего общего с XAML.

Интерпретация текста инициализации в классах расширения

Строковые маркеры после имени расширения разметки, которые остаются в фигурных скобках, интерпретируются обработчиком XAML одним из следующих способов.

  • Запятая всегда представляет собой разделитель или ограничитель для отдельных токенов.

  • Если отдельные разделенные маркеры не содержат ни одного знака равенства, каждый маркер рассматривается как аргумент конструктора. Каждый параметр конструктора должен быть задан в качестве типа, ожидаемого этой сигнатурой, и в правильном порядке, ожидаемом этой сигнатурой.

    Замечание

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

  • Если отдельные разделенные маркеры содержат знаки равенства, обработчик XAML сначала вызывает конструктор без параметров для расширения разметки. Затем каждая пара name=value интерпретируется как имя свойства, существующее в расширении разметки, и значение, которое присваивается этому свойству.

  • Если существует параллельный результат между поведением конструктора и поведением параметра свойства в расширении разметки, это не имеет значения, какое поведение вы используете. Чаще всего используются пары свойство=значение для расширений разметки, которые имеют более одного настраиваемого свойства, поскольку это делает вашу разметку более продуманной, и вы менее вероятно случайно переставите параметры конструктора. (При указании пар property=value эти свойства могут находиться в любом порядке.) Кроме того, не гарантируется, что расширение разметки предоставляет параметр конструктора для настройки каждого из его настраиваемых свойств. Например, Binding это расширение разметки, с множеством свойств, которые задаются с помощью расширения в форме свойства=значения, но Binding поддерживает только два конструктора: конструктор без параметров и один, который задает начальный путь.

  • Литеральная запятая не может быть передана расширению разметки без экранирования.

Escape-последовательности и расширения разметки

Обработка атрибутов в обработчике XAML использует фигурные скобки в качестве индикаторов последовательности расширения разметки. Кроме того, при необходимости можно создать значение атрибута в виде символа фигурной скобки, введя escape-последовательность с помощью пустой пары фигурных скобок, с последующей литеральной фигурной скобкой. Смотри {} Escape-последовательность — расширение разметки.

Использование вложенных расширений разметки в XAML

Вложение нескольких расширений разметки поддерживается, и каждое расширение разметки будет оцениваться в первую очередь. Например, рассмотрим следующее использование:

<Setter Property="Background"
  Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" />

В этом использовании оператор x:Static сначала оценивается и возвращает строку. Затем эта строка используется в качестве аргумента для DynamicResource.

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

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

Большинство расширений разметки, используемых в синтаксисе элемента объекта для заполнения элемента свойства, не будут иметь содержимого или какого-либо дополнительного синтаксиса элемента свойства внутри него. Таким образом, вы закроете тег элемента объекта и не укажите дочерние элементы. Всякий раз, когда любой элемент объекта обнаруживается обработчиком XAML, вызывается конструктор для этого класса, который создает экземпляр объекта, созданного из синтаксического элемента. Класс расширения разметки не отличается: если вы хотите, чтобы расширение разметки было доступно в синтаксисе элемента объекта, необходимо предоставить конструктор без параметров. Некоторые существующие расширения разметки имеют по крайней мере одно необходимое значение свойства, которое необходимо указать для эффективной инициализации. Если да, это значение свойства обычно присваивается в качестве атрибута свойства в элементе объекта. На страницах справочника по языковым возможностям пространства имен XAML (x:) и расширениям XAML WPF будут отмечены расширения разметки, имеющие требуемые свойства (и названия этих свойств). Справочные страницы также отмечают, запрещен ли синтаксис элемента объекта или синтаксис атрибута для определенных расширений разметки. Заметным случаем является расширение разметки x:Array, которое не поддерживает синтаксис атрибутов, так как содержимое этого массива должно быть указано в теге как содержимое. Содержимое массива обрабатывается как общие объекты, поэтому не существует преобразователя типов по умолчанию для атрибута. Кроме того, для расширения разметки x:Array требуется type параметр.

См. также