TypeConverters и XAML
Этот раздел посвящен цели преобразования типов из строк — одной из основных функций языка XAML. В платформе .NET Framework класс TypeConverter служит конкретной цели как часть реализации управления пользовательским классом, который может использоваться в качестве значения свойства при использовании атрибута XAML. При написании пользовательского класса, если необходимо, чтобы экземпляры класса могли использоваться как значения настраиваемого атрибута XAML, может понадобиться применение атрибута TypeConverterAttribute к классу, написание пользовательского класса TypeConverter или оба действия.
В этом разделе содержатся следующие подразделы.
- Концепции преобразования типов
- Реализация преобразователя типов
- Применение TypeConverterAttribute
- Связанные разделы
Концепции преобразования типов
XAML и строковые параметры
Когда задается значение атрибута в файле XAML, начальный тип этого значения — строка чистого текста. Даже такие примитивы, как Double, первоначально для обработчика XAML являются текстовыми строками.
XAML-обработчику требуется два сообщения для того, чтобы обработать значение атрибута. Первое сообщение является типом значения устанавливаемого свойства. Любая строка, которая определяет значение атрибута и обрабатывается в XAML, в конечном счете должна быть приведена к значению этого типа. Если значение является примитивом, понятным средству синтаксического анализа XAML (например, числовое значение), будет произведена попытка прямого преобразования. Если значение является перечислением, то строка используется для проверки совпадения имени в этом перечислении с именем константы. Если значение не является ни примитивом, понятным средству синтаксического анализа, ни перечислением, то этот тип должен обладать возможностью предоставления экземпляра типа или значения, основанного на преобразованной строке. Это делается указанием класса преобразователя типа. Преобразователь типа — это, фактически, вспомогательный класс, предоставляющий значения другого класса как сценариям XAML, так и, потенциально, вызовам из кода .NET.
Использование поведения преобразования существующего типа в XAML
В зависимости от уровня понимания концепций XAML, вы, возможно, уже используете преобразование типа в простом приложении XAML, не реализуя его. WPF, например, определяет сотни свойств, принимающих значение типа Point. Значение Point описывает координаты в двухмерном пространстве координат и обладает всего двумя важными свойствами: X и Y. При определении точки в XAML она задается в виде строки с разделителем (обычно запятой) между предоставляемыми значениями X и Y. Например: <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">.
Даже этот простой тип Point и простое его использование в XAML используют преобразователь типа. В данном случае это класс PointConverter.
Преобразователь типа для типа Point определяется на уровне класса и упрощает разметку всех свойств, принимающих значение типа Point. Без преобразователя типа для создания примера, показанного выше, требуется гораздо больше разметки.
<LinearGradientBrush>
<LinearGradientBrush.StartPoint>
<Point X="0" Y="0"/>
</LinearGradientBrush.StartPoint>
<LinearGradientBrush.EndPoint>
<Point X="1" Y="1"/>
</LinearGradientBrush.EndPoint>
<LinearGradientBrush>
Использовать преобразование типа строки или более многословный синтаксис — этот выбор диктуется только стилем написания кода. Инструментарий рабочего процесса XAML также может оказывать влияние на то, как задаются значения. Некоторые инструменты XAML склонны создавать очень подробную разметку, поскольку это облегчает переключение между представлениями конструктора и собственным механизмом сериализации.
Существующие преобразователи типов могут быть найдены для типов WPF и платформы .NET Framework путем проверки класса (или свойства) на наличие примененного атрибута TypeConverterAttribute. Этот атрибут содержит имя класса, поддерживающего преобразование для данного типа, как для XAML, так, потенциально, и для других целей.
Преобразователи типа и расширения разметки
Расширения разметки и преобразователи типа играют ортогональные роли в терминах поведения обработчика XAML и сценариев, к которым они применяются. Хотя контекст доступен для использования расширения разметки, поведение преобразования типов свойств в случаях, где расширение разметки предоставляет значение, обычно не проверяется в реализациях расширения разметки. Другими словами, даже если расширение разметки в качестве своих выходных данных ProvideValue возвращает текстовую строку, поведение преобразования типа для этой строки в применении к конкретному свойству или типу значения свойства не вызывается. Обычно целью расширения разметки является обработка строки и возврат объекта без использования какого бы то ни было преобразователя типа.
Одна общая ситуация, где необходимо расширение разметки, а не преобразователь типа, заключается в создании ссылки на объект, который уже существует. В лучшем случае преобразователь типа с неопределенным состоянием может только создать новый экземпляр, что может быть нежелательно. Дополнительные сведения о расширениях разметки см. в разделе Расширения разметки и XAML WPF.
Собственные преобразователи типа
В реализации средства синтаксического анализа XAML в WPF и платформе .NET Framework существуют несколько типов, поддерживающих собственную обработку преобразования типа, но нет типов, которые можно рассматривать как примитивы. Примером такого типа является тип DateTime. Причина этого кроется в архитектуре платформы .NET Framework: тип DateTime определен в библиотеке mscorlib, основной библиотеке .NET. Для типа DateTime не разрешено назначение атрибута из иной сборки, нежели та, что вводит зависимость (атрибут TypeConverterAttribute принадлежит сборке System), таким образом, обычный механизм поиска преобразователя типа через атрибут не может поддерживаться. Вместо этого в средстве синтаксического анализа XAML имеется список типов, для которых необходима такая встроенная обработка; такие типы обрабатываются так же, как настоящие примитивы. (В случае с типом DateTime это приводит к вызову метода Parse.
Реализация преобразователя типов
TypeConverter
В приведенном ранее примере с типом Point упоминается класс PointConverter. В реализации XAML на платформе .NET все типы преобразователей, используемые для нужд XAML, являются классами, производными от базового класса TypeConverter. Класс TypeConverter присутствует в версиях платформы .NET Framework, предшествующих появлению XAML; одной из первоначальных задач, решаемых с его помощью, было преобразование строк для диалогов свойств в визуальных конструкторах. Для XAML роль класса TypeConverter расширяется: теперь это базовый класс для преобразований в строку и из строки, позволяющий анализ строчного значения атрибута, и, возможно, преобразование значения времени выполнения определенного свойства объекта обратно в строку для сериализации в качестве атрибута.
В классе TypeConverter определены четыре элемента, относящихся к преобразованию в строки и из строк для нужд обработки XAML.
Из них наиболее важен метод ConvertFrom. Этот метод преобразует входную строку к требуемому типу объекта. Строго говоря, метод ConvertFrom может быть реализован для преобразования значительно более широкого диапазона типов в заданный преобразователем конечный тип. Это служит целям, выходящим за пределы XAML, таким как поддержка преобразований времени выполнения, но при использовании с XAML это только путь к коду, который может обработать ввод String нужным образом.
Вторым по важности методом является ConvertTo. Если приложение преобразуется в представление разметки (например, если оно сохраняется в файл XAML), метод ConvertTo отвечает за создание представления разметки. В этом случае правильный для XAML путь — передача параметра destinationType для значения типа String.
CanConvertTo и CanConvertFrom поддерживают методы, которые используются тогда, когда службы запрашивают характеристики реализации TypeConverter. Необходимо реализовать эти методы так, чтобы они возвращали значение true для случаев, специфичных для типа, таким же образом, как аналогичные методы преобразования вашей поддержки преобразования. Для нужд XAML это обычно тип String.
Сведения о языке и региональных параметрах и преобразователи типа в XAML
Каждая реализация TypeConverter может иметь собственную интерпретацию того, что составляет допустимую строку для преобразования, а также может использовать или игнорировать описание типа, переданного в качестве параметров. Важное замечание относительно языка и региональных параметров и преобразования типов XAML. Использование локализуемых строк в качестве значений атрибутов полностью поддерживается в XAML. Но использование локализуемых строк в качестве входных данных преобразователя типа с учетом индивидуальных требований для языка и региональных параметров не поддерживается, поскольку преобразователи типа значений атрибутов XAML по необходимости выполняют анализ с фиксированным языком, используя язык и региональные параметры en-US. Дополнительные сведения о причинах этого ограничения с точки зрения проектирования см. в спецификации языка XAML ([MS-XAML]).
Пример того, что учет языка и региональных параметров может быть важен: некоторые языки и региональные параметры используют запятую в качестве десятичного разделителя. Это входит в противоречие с поведением многих преобразователей типа WPF XAML, которые используют запятую в качестве разделителя (исторически в обычной форме X,Y или в списках, разделенных запятыми). Даже передача языка и региональных параметров в окружающий XAML (установка параметра Language или xml:lang в значение sl-SI, как пример языка и региональных параметров, использующих запятую в качестве десятичного разделителя) не решает проблемы.
Реализация ConvertFrom
Чтобы использоваться в качестве реализации класса TypeConverter, поддерживающей XAML, метод ConvertFrom этого преобразователя должен принимать строку в качестве параметра value. Если строка в допустимом формате и может быть преобразована с помощью реализации TypeConverter, то возвращаемый объект должен поддерживать возможность приведения к типу, ожидаемому свойством. В противном случае реализация ConvertFrom должна возвращать null.
Каждая реализация TypeConverter может иметь собственную интерпретацию того, что составляет допустимую строку для преобразования, а также может использовать или игнорировать описание типа или контекстов языка и региональных параметров, переданных в качестве параметров. Тем не менее обработка WPF XAML может не передать значения в контекст описания типа во всех случаях, а также может не передать язык и региональные параметры на основе xml:lang.
Примечание |
---|
Не используйте фигурные скобки, особенно {, как возможный элемент формата строки.Эти знаки зарезервированы как вход и выход для последовательности расширения разметки. |
Реализация ConvertTo
ConvertTo можно потенциально использовать для поддержки сериализации. Поддержка сериализации с помощью метода ConvertTo не является обязательным требованием для пользовательского типа или его преобразователя. Однако, при реализации элемента управления или используя сериализацию, как часть функций, или разрабатывая класс, следует реализовать ConvertTo.
Для использования в качестве реализации типа TypeConverter, поддерживающей XAML, метод ConvertTo данного преобразователя должен принимать экземпляр типа (или значение), поддерживаемый в качестве параметра value. Если параметр destinationType является типом String, то возвращаемый объект должен быть способен изменять тип на String. Возвращаемая строка должна отображать сериализованное значение value. В идеальном случае выбранный формат сериализации должен поддерживать создание того же значения, в случае передачи этой строки реализации ConvertFrom того же преобразователя, без значительной потери информации.
Если значение не может быть сериализовано, или преобразователь не поддерживает сериализацию, реализация ConvertTo должна возвращать null и разрешается выбросить исключение в данном случае. При создании исключения необходимо заявить о невозможности использования этого преобразователя в качестве части реализации метода CanConvertTo, поэтому рекомендуется производить предварительную проверку с помощью метода CanConvertTo, чтобы избежать исключений.
Если параметр destinationType не из типов String, то можно выбрать собственную обработку преобразователя. В обычном случае вы возвращаетесь к обработке базовой реализации, в которой каждый метод ConvertTo создает определенное исключение.
Реализация CanConvertTo
Ваша реализация CanConvertTo должна возвращать true для destinationType типа String, в противном случае передавать базовой реализации.
Реализация CanConvertFrom
Реализация CanConvertFrom должна возвращать true для sourceType типа String, а в противном случае откладывать до базовой реализации.
Применение TypeConverterAttribute
Для того чтобы использовать пользовательский преобразователь типа в качестве действующего преобразователя типа для пользовательского класса обработчика XAML, необходимо применить .NET Framework attribute TypeConverterAttribute к определению класса. ConverterTypeName, указываемое посредством атрибута, должно быть именем типа преобразователя пользовательского типа. Если этот атрибут применен, то в случае, когда обработчик XAML обрабатывает значения, в которых тип свойства использует тип пользовательского класса, обработчик может ввести строки и вернуть экземпляры объекта.
Можно также предоставить преобразователь типа на основе каждого свойства. Вместо применения .NET Framework attribute TypeConverterAttribute к определению класса, следует применить его к определению свойства (главное определение, не реализации get/set внутри него). Тип свойства должен соответствовать типу, который обрабатывается пользовательским преобразователем типа. Если этот атрибут применен, то в случае, когда обработчик XAML обрабатывает значения этого свойства, он может обработать входные строки и вернуть экземпляры объекта. Преобразователь типа каждого свойства особенно полезен в случае, если выбрано использование типа свойства из Microsoft .NET Framework или из какой-либо другой библиотеки, в которой нельзя управлять определением класса и нельзя применять TypeConverterAttribute.
См. также
Ссылки
Основные понятия
Общие сведения о языке XAML (WPF)