Обзор преобразователей типов для XAML
Преобразователи типов предоставляют логику записи объектов, которая преобразуется из строки разметки XAML в определенные объекты в графе объектов. В службах XAML .NET преобразователь типов должен быть классом, производным от TypeConverter. Некоторые преобразователи также поддерживают путь сохранения XAML и могут использоваться для сериализации объекта в строковую форму в разметке сериализации. В этом разделе описывается, как и когда вызываются преобразователи типов в XAML, а также даются рекомендации по реализации для переопределений метода TypeConverter.
Понятия преобразования типов
В следующих разделах описываются основные понятия о том, как XAML использует строки и как записи объектов в службах XAML .NET используют преобразователи типов для обработки некоторых строковых значений, встречающихся в источнике XAML.
XAML и строковые значения
При установке значения атрибута в XAML-файле начальный тип этого значения является строкой в общем смысле и строковым значением атрибута в xml-смысле. Даже другие примитивы, такие как Double, изначально являются строками процессора XAML.
В большинстве случаев обработчик XAML нуждается в двух фрагментах информации для обработки значения атрибута. Первая часть информации — это тип значения заданного свойства. Любая строка, определяющая значение атрибута и обрабатываемая в XAML, в конечном счете должна быть преобразована или разрешена в значение этого типа. Если значение является примитивом, понятным средством синтаксического анализа XAML (например, числовым значением), выполняется прямое преобразование строки. Если значение атрибута ссылается на перечисление, указанная строка проверяется на соответствие имени именованной константе в этом перечислении. Если значение не является примитивом синтаксического анализа или именем константы из перечисления, применимый тип должен иметь возможность предоставить значение или ссылку, основанную на преобразованной строке.
Заметка
Директивы языка XAML не используют преобразователи типов.
Преобразователи типов и расширения разметки
Использование расширения разметки должно быть обработано процессором XAML, прежде чем он проверит тип свойства и другие аспекты. Например, если свойство, заданное в качестве атрибута, обычно имеет преобразование типов, но в конкретном случае определяется использованием расширения разметки, то поведение расширения разметки сначала обрабатывается. Одна из распространенных ситуаций, когда необходимо расширение разметки, заключается в том, чтобы сделать ссылку на объект, который уже существует. В этом сценарии преобразователь типов, не имеющий состояния, может создавать только новый экземпляр, что может оказаться нежелательным. Дополнительные сведения о расширениях разметки см. в Обзор расширений разметки для XAML.
Встроенные преобразователи типов
В реализациях служб Windows Presentation Foundation (WPF) и .NET XAML существуют определенные типы CLR, которые имеют нативную обработку преобразования типов. Однако эти типы CLR обычно не считаются примитивами. Пример такого типа — DateTime. Одна из причин заключается в том, как работает архитектура .NET Framework: тип DateTime определен в mscorlib, самой базовой библиотеке в .NET. DateTime не допускается быть атрибутированным атрибутом, поступающим из другой сборки, которая вводит зависимость (TypeConverterAttribute относится к System). Поэтому обычный механизм обнаружения преобразователя типов путем атрибутирования не может поддерживаться. Вместо этого средство синтаксического анализа XAML содержит список типов, требующих собственной обработки, и он обрабатывает эти типы, аналогичные тому, как обрабатываются истинные примитивы. В случае DateTimeэта обработка включает вызов Parse.
Реализация преобразователя типов
В следующих разделах рассматривается API класса TypeConverter.
TypeConverter
В службах XAML .NET все преобразователи типов, используемые для целей XAML, являются классами, производными от базового класса TypeConverter. Класс TypeConverter существовал в версиях .NET Framework до существования XAML; одним из исходных сценариев TypeConverter было предоставление преобразования строк для редакторов свойств в визуальных конструкторах.
Для XAML расширена роль TypeConverter. В целях XAML TypeConverter является базовым классом для обеспечения поддержки определённых преобразований в строковый формат и из строкового формата. Функция "From-string" позволяет синтаксически анализировать строковое значение атрибута в XAML. Преобразование в строку может позволить обработать значение определенного свойства объекта во время выполнения и обратно преобразовать его в атрибут XAML для сериализации.
TypeConverter определяет четыре члена, связанных с преобразованием в строку и обратно из строки для целей обработки XAML.
Из этих элементов наиболее важным методом является ConvertFrom, который преобразует входную строку в требуемый тип объекта. Метод ConvertFrom можно реализовать для преобразования более широкого диапазона типов в целевой тип преобразователя. Поэтому он может служить целям, которые выходят за рамки XAML, такие как поддержка преобразований во время выполнения. Однако при использовании XAML важен только тот путь кода, который может обрабатывать вход String.
Второй наиболее важный метод — ConvertTo. Если приложение преобразуется в представление разметки (например, если оно сохраняется в XAML в виде файла), ConvertTo участвует в более крупном сценарии записи текста XAML для создания представления разметки. В этом случае важный путь кода для XAML — когда вызывающий объект передаёт destinationType
из String.
CanConvertTo и CanConvertFrom - это вспомогательные методы, которые используются, когда служба запрашивает возможности реализации TypeConverter. Эти методы необходимо реализовать, чтобы возвращать true
для случаев, специфичных для типа, которые поддерживают эквивалентные методы преобразования вашего преобразователя. В целях XAML это обычно означает тип String.
Информация о культуре и преобразователи типов для XAML
Каждая реализация TypeConverter может однозначно интерпретировать то, что является допустимой строкой для преобразования, и она также может использовать или игнорировать описание типа, передаваемое в качестве параметров. Важно учитывать следующее при преобразовании типов и использовании XAML в контексте культурных особенностей: хотя XAML поддерживает использование локализуемых строк в качестве значений атрибутов, вы не можете использовать эти локализуемые строки в качестве входных данных для преобразователя типов с конкретными культурными требованиями. Это ограничение обусловлено тем, что преобразователи типов для значений атрибутов XAML включают обязательно фиксированное языковое поведение обработки XAML, использующее культуру en-US
. Дополнительные сведения о причинах разработки этого ограничения см. в спецификации языка XAML ([MS-XAML]) или в обзоре глобализации и локализации для WPF .
В качестве примера, где культура может быть проблемой, некоторые культуры используют запятую вместо точки в качестве разделителя для десятичных чисел в строковой форме. Это использование вступает в конфликт с поведением многих существующих преобразователей типов, которые используют запятую в качестве разделителя. Передача культуры через xml:lang
в окружающем XAML не решает проблему.
Реализация ConvertFrom
Чтобы использовать его как реализацию TypeConverter, поддерживающую XAML, метод ConvertFrom для этого преобразователя должен принимать строку в качестве параметра value
. Если строка находится в допустимом формате и может быть преобразована реализацией TypeConverter, возвращаемый объект должен поддерживать приведение к типу, ожидаемому свойством. В противном случае реализация ConvertFrom должна возвращать null
.
Каждая реализация TypeConverter может уникально интерпретировать, что представляет собой допустимую строку для процесса преобразования. Она также может использовать или игнорировать описание типа или культурные контексты, передаваемые в качестве параметров. Однако обработка XAML WPF может не передавать значения в контекст описания типа во всех случаях, а также может не передавать культурные данные, основанные на xml:lang
.
Заметка
Не используйте фигурные скобки ({}), в частности открывающую скобку ({), в качестве элемента строкового формата. Эти символы зарезервированы как вход и выход для последовательности расширения разметки.
Необходимо создать исключение в случае, если преобразователь типов должен получить доступ к службе XAML через запись объектов .NET XAML Services, но вызов GetService, сделанный в данном контексте, не возвращает эту службу.
Реализация метода ConvertTo
ConvertTo потенциально используется для поддержки сериализации. Поддержка сериализации с помощью ConvertTo для пользовательского типа и его преобразователя типов не является абсолютным требованием. Однако если вы реализуете элемент управления или используете сериализацию в рамках функций или проектирования класса, следует реализовать ConvertTo.
Чтобы использовать его как реализацию TypeConverter, поддерживающую XAML, метод ConvertTo для этого преобразователя должен принимать экземпляр типа (или значения), который поддерживается в качестве параметра value
. Если параметр destinationType
имеет тип String, возвращаемый объект должен иметь возможность приведения как String. Возвращаемая строка должна представлять сериализованное значение value
. В идеале формат сериализации, который вы выбрали, должен иметь возможность создать то же значение, что и если бы эта строка была передана в ConvertFrom реализации того же преобразователя, без значительной потери информации.
Если значение не может быть сериализовано или преобразователь не поддерживает сериализацию, реализация ConvertTo должна возвращать null
и может вызывать исключение. Однако если вы действительно вызываете исключения, следует сообщить о невозможности использовать это преобразование как часть вашей реализации CanConvertTo, чтобы поддержать передовую практику сначала проверять CanConvertTo, чтобы избежать исключений.
Если параметр destinationType
не имеет типа String, можно выбрать собственную обработку преобразователя. Как правило, вы вернеесь к базовой обработке реализации, которая в базовом ConvertTo вызывает определенное исключение.
Необходимо создать исключение, если преобразователь типов должен иметь доступ к службе XAML из модуля записи объектов .NET XAML Services, но вызов GetService, сделанный в контексте, не возвращает ту службу.
Реализация CanConvertFrom
Реализация CanConvertFrom должна возвращать true
для sourceType
типа String и в противном случае отложить в базовую реализацию. Не вызывайте исключения из CanConvertFrom.
Реализация метода CanConvertTo
Реализация CanConvertTo должна возвращать true
для destinationType
типа String, в противном случае передать выполнение базовой реализации. Не вызывайте исключения из CanConvertTo.
Применение TypeConverterAttribute
Чтобы настраиваемый преобразователь типов использовался в качестве преобразователя типов действия для пользовательского класса служб XAML .NET, необходимо применить TypeConverterAttribute к определению класса. ConverterTypeName, которые вы указываете с помощью атрибута, должны быть именем типа вашего пользовательского преобразователя типов. Если этот атрибут применяется, когда обработчик XAML обрабатывает значения, в которых тип свойства использует тип пользовательского класса, он может вводить строки и возвращать экземпляры объектов.
Можно также предоставить преобразователь типов на основе каждого свойства. Вместо применения TypeConverterAttribute к определению класса примените его к определению свойства (основное определение, а не реализации get
/set
в нем). Тип свойства должен соответствовать типу, обрабатываемму пользовательским преобразователем типов. При применении этого атрибута, когда обработчик XAML обрабатывает значения этого свойства, он может обрабатывать входные строки и возвращать экземпляры объектов. Метод типового конвертера для каждого свойства полезен, если вы решили использовать тип свойства из Microsoft .NET Framework или из другой библиотеки, где нельзя управлять определением класса и нельзя применить TypeConverterAttribute там.
Чтобы предоставить поведение преобразования типов для настраиваемого присоединенного элемента, примените TypeConverterAttribute к методу доступа Get
шаблона реализации для присоединенного элемента.
Доступ к контексту поставщика услуг из реализации расширения разметки
Доступные службы одинаковы для любого преобразователя значений. Разница заключается в том, как каждый преобразователь значений получает контекст службы. Доступ к службам и информацию о доступных службах можно найти в разделе Преобразователи типов и расширения разметки для XAML.
Преобразователи типов в потоке узлов XAML
Если вы работаете с потоком узлов XAML, действие или конечный результат преобразователя типов еще не выполняется. В пути загрузки строка атрибута, которая в конечном итоге должна быть преобразована в тип для загрузки, остается текстовым значением в начальном и конечном элементе. Преобразователь типов, который в конечном итоге необходим для этой операции, можно определить с помощью свойства XamlMember.TypeConverter. Однако получение допустимого значения из XamlMember.TypeConverter зависит от контекста схемы XAML, который может получить доступ к такой информации через базовый член или тип значения объекта, используемого элементом. Для вызова поведения преобразования типов также требуется контекст схемы XAML, так как для этого требуется сопоставление типов и создание экземпляра преобразователя.
См. также
.NET Desktop feedback