TypeConverters и XAML

Этот раздел посвящен цели преобразования типов из строк — одной из основных функций языка XAML. в платформа .NET Framework TypeConverter класс выполняет определенную цель как часть реализации управляемого пользовательского класса, который может использоваться как значение свойства в использовании атрибута XAML. При написании пользовательского класса и необходимости использовать экземпляры класса в качестве значений атрибутов, устанавливаемых в XAML, может потребоваться применить TypeConverterAttribute к классу, написать пользовательский TypeConverter класс или и то, и другое.

Понятия преобразования типов

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 разворачивается так, чтобы включать в себя базовый класс для преобразования строк и из строк, которые позволяют анализировать значение атрибута String, и, возможно, обработку значения времени выполнения определенного свойства объекта обратно в строку для сериализации в качестве атрибута.

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, необходимо применить TypeConverterAttribute к определению класса. Имя ConverterTypeName , указываемое в атрибуте, должно быть именем типа пользовательского преобразователя типов. Если этот атрибут применен, то в случае, когда обработчик XAML обрабатывает значения, в которых тип свойства использует тип пользовательского класса, обработчик может ввести строки и вернуть экземпляры объекта.

Вы также можете предоставить преобразователь типов для отдельных свойств. Вместо применения TypeConverterAttribute к определению класса примените его к определению свойства (основное определение, а не к get/set реализации внутри него). Тип свойства должен соответствовать типу, который обрабатывается пользовательским преобразователем типов. Если этот атрибут применяется, обработчик XAML может обработать входные строки и вернуть экземпляры объекта при работе со значениями этого свойства. использование преобразователя типов для каждого свойства особенно полезно, если вы решили использовать тип свойства из Microsoft платформа .NET Framework или из другой библиотеки, где нельзя управлять определением класса и применять его TypeConverterAttribute .

См. также