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


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 вы указываете ее как строку с разделителем (обычно запятой) между XY предоставленными значениями. Например: <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 . Для .NET реализаций XAML все преобразователи типов, используемые в целях XAML, являются классами, которые наследуются от базового класса TypeConverter. Класс TypeConverter существовал в версиях .NET Framework, предшествующих существованию XAML. Одно из его исходных использования — обеспечить преобразование строк для диалогов свойств в визуальных конструкторах. Для XAML роль TypeConverter расширяется, чтобы включать в себя базовый класс, который поддерживает преобразование в строку и из строки, что позволяет разбирать значение строкового атрибута, а также, возможно, обрабатывать значение свойства объекта во время выполнения, преобразовывая его обратно в строку для сериализации в качестве атрибута.

TypeConverter определяет четыре члена, которые относятся к преобразованию в строки и из строк для целей обработки XAML:

Из них наиболее важным является метод ConvertFrom. Этот метод преобразует входную строку в требуемый тип объекта. Строго говоря, ConvertFrom метод может быть реализован для преобразования гораздо более широкого диапазона типов в предполагаемый тип назначения преобразователя, и таким образом служит целям, которые выходят за рамки XAML, таких как поддержка преобразований во время выполнения, но для целей XAML это только путь кода, который может обрабатывать String входные данные, которые имеют значение.

Следующим наиболее важным методом является ConvertTo. Если приложение преобразуется в представление разметки (например, если оно сохраняется в XAML в виде файла), ConvertTo отвечает за создание представления разметки. В этом случае путь кода, который имеет значение для XAML, заключается в передаче destinationTypeString объекта .

CanConvertTo и CanConvertFrom - это вспомогательные методы, которые используются, когда служба запрашивает возможности реализации TypeConverter. Эти методы необходимо реализовать, чтобы возвращать true для случаев, специфичных для типа, которые поддерживают эквивалентные методы преобразования вашего преобразователя. В целях XAML это обычно означает тип String.

Информация о культуре и преобразователи типов для XAML

Каждая TypeConverter реализация может иметь собственную интерпретацию того, что представляет собой допустимую строку для преобразования, а также может использовать или игнорировать описание типа, переданное в качестве параметров. Есть важный момент, касающийся культуры и преобразования типов XAML. Использование локализуемых строк в качестве значений атрибутов полностью поддерживается XAML. Но использование этой локализуемой строки в качестве входных данных для преобразователя типов с специфическими региональными требованиями не поддерживается, так как преобразователи типов для значений атрибутов XAML включают обязательное языковое поведение синтаксического анализа с использованием en-US культуры. Дополнительные сведения о причинах разработки этого ограничения см. в спецификации языка XAML ([MS-XAML].

В качестве примера, когда язык и региональные параметры могут быть проблемой, некоторые язык и региональные параметры используют запятую в качестве разделителя десятичных точек для чисел. Это приведет к взаимодействию с поведением, которое имеет многие преобразователи типов XAML WPF, которое заключается в использовании запятой в качестве разделителя (на основе исторических прецедентов, таких как общая форма X,Y или разделенные запятыми списки). Даже передача культуры в окружающем XAML (настройка Language или xml:lang на sl-SI, пример культуры, использующей запятую для десятичных знаков) не решает проблему.

Реализация ConvertFrom

Чтобы использовать его как реализацию TypeConverter, поддерживающую XAML, метод ConvertFrom для этого преобразователя должен принимать строку в качестве параметра value. Если строка была в допустимом формате и может быть преобразована TypeConverter реализацией, возвращаемый объект должен поддерживать приведение к типу, ожидаемому свойством. В противном случае реализация ConvertFrom должна возвращать null.

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

См. также