Определение DataTemplate. DataType с пользовательским расширением типа

У меня есть это расширение разметки

public class NullableExtension : TypeExtension
{
    public NullableExtension() {
    }

    public NullableExtension( string type )
        : base(type) {
    }

    public NullableExtension( Type type )
        : base(type) {
    }

    public override object ProvideValue( IServiceProvider serviceProvider ) {
        Type basis = (Type)base.ProvideValue( serviceProvider );
        return typeof(Nullable<>).MakeGenericType( basis );
    }
}

который разработан для обеспечения nullable версии некоторого другого типа. Это работает как ожидалось при использовании в "нормальном" XAML. Например, как в

<SomeControl DataContext="{My:Nullable System:Int32}"/>

(предполагающий, что Мой - пространство имен XML, определенное для пространства имен C#, содержащего расширение, и так же для Системы). Контекст данных для управления установлен на a System.Type для Nullable<int> поскольку я ожидаю.

Однако, когда я использую это расширение, чтобы попытаться установить DataType свойство a DataTemplate как

<DataTemplate DataType="{My:Nullable System:Int32}">
  <TextBlock ... />
</DataTemplate>

Мне говорят, компилятором, этим

Ключ для словаря не может иметь типа 'Система. Windows. Средства управления. Примитивы. TextBlock'. Только Строка, TypeExtension и StaticExtension поддерживаются."

и

"Ни у какого конструктора для типа 'NullableExtension' нет 1 параметра.

Делает кто-либо знает почему только те три метода (и даже подклассы TypeExtension, как мой), позволяются? Что является особенным об обработке XAML в той точке? И есть ли другой способ выполнить это (шаблонный выбор данных на основе типов, которые могут быть nullable), не обращаясь к a DataTemplateSelector?

9
задан Adi Lester 19 October 2012 в 21:23
поделиться

2 ответа

Я действительно вник в ваш вопрос, и вот что я нашел.

В: Почему разрешены только эти три ( String , TypeExtension и StaticExtension )?

A: Автор дизайн. Если бы вы могли написать любое собственное расширение разметки для использования в качестве ключа в словаре, какие побочные эффекты это привело бы? Представьте, что у вас есть Binding как значение DataType ... Я уверен, что вы можете добавить десятки проблем, связанных с динамическим характером словарных ключей.

Вопрос: Что особенного в обработке XAML на этом этапе?

A . На этом этапе у вас есть создание BAML. Проблема исходит от внутреннего класса BamlRecordWriter , но сообщение не описывает реальную проблему. Когда вы указываете настраиваемое расширение разметки как DataType, он берет дочерний элемент DataTemplate и проверяет его, можно ли его присвоить из строки, TypeExtension или StaticExtension (см. функцию BamlRecordWriter.WriteElementStart () ). Действительно. Не ваше расширение (которое назначается TypeExtension), а первый дочерний элемент (который не назначается). Теперь у вас есть странная вещь « не может быть типа ». Хотя это похоже на ошибку BamlRecordWriter, я думаю, они оставили ее намеренно. Пока это не позволит вам использовать настраиваемое расширение разметки в качестве значения DataType, кого волнует сообщение об ошибке?

Q: Есть ли другой способ сделать это (выбор шаблона данных на основе типов, которые могут допускать значение NULL) без прибегая к DataTemplateSelector?

A: Да, вроде. Прежде всего, вы можете использовать стандартное расширение TypeExtension, которое сделает всю грязную работу за вас:

<DataTemplate DataType="{x:Type TypeName=System:Nullable`1[[System.Int32]]}">
</DataTemplate>

Но в большинстве случаев (если не всегда) вы не увидите результатов создания шаблонов. Почему? Теперь дело доходит до правил упаковки для типов, допускающих значение NULL. Упаковка ненулевого типа значения, допускающего значение NULL, помещает сам тип значения, а не System.Nullable, который является оболочкой для типа значения. Таким образом, селектор шаблонов по умолчанию будет искать DataTemplate с DataType T , а не Nullable .

Я могу не понять точную проблему, которую вы пытаетесь решить с помощью расширения, допускающего значение NULL, но вы можете обернуть обнуляемые значения в свой собственный тип ссылки, написать один DataTemplate для оболочки и использовать DataTemplate.Triggers для выбора внешнего вида содержимого. Что ж, это похоже на заново изобретенный селектор шаблонов данных :) ...

NB: Я не парень из MS, и мои выводы основаны на Reflector и моем собственном опыте (который не такой большой, как мне хотелось бы alt text ). В любом случае, надеюсь, что смогу помочь :).

Ура

12
ответ дан 4 December 2019 в 12:18
поделиться

Синтаксис

DataType="{x:Type TypeName=System:Nullable`1[[System.Int32]]}">

, похоже, не работает для типов, определенных пользователем :(

На самом деле есть еще один способ - создать базовый неуниверсальный тип. Установите первый шаблон данных для этого типа и привяжите ContentPresenter .Content к свойству, содержащему объект T . Затем создайте другие шаблоны данных для любого T .

2
ответ дан 4 December 2019 в 12:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: