Как сослаться на универсальный тип в атрибуте DataType HierarchicalDataTemplate?

  • Использование ICU для контакта с Вашими данными (или подобная библиотека)
  • В Вашем собственном хранилище данных, удостоверьтесь, что все хранится в том же кодировании
  • , Удостоверяются, что Вы всегда пользуетесь своей unicode библиотекой для приземленных задач как длина строки, состояние капитализации, и т.д. Никогда не пользуетесь стандартной библиотекой builtins как is_alpha, если это не определение, Вы хотите.
  • я не могу сказать это достаточно: никогда не выполняют итерации по индексам string, если Вы заботитесь о правильности, всегда пользуетесь своей unicode библиотекой для этого.
7
задан psubsee2003 17 January 2015 в 19:54
поделиться

2 ответа

itowlson's approach is a good one but it is just a start. Here's something that will work for your case (and most, if not all, cases):

public class GenericType : MarkupExtension
{
    public Type BaseType { get; set; }
    public Type[] InnerTypes { get; set; }

    public GenericType() { }
    public GenericType(Type baseType, params Type[] innerTypes)
    {
        BaseType = baseType;
        InnerTypes = innerTypes;
    }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        Type result = BaseType.MakeGenericType(InnerTypes);
        return result;
    }
}

Then, you are able to create any type with any level of depth in your XAML. For example:

    <Grid.Resources>
        <x:Array Type="{x:Type sys:Type}" 
                 x:Key="TypeParams">
            <x:Type TypeName="sys:Int32" />
        </x:Array>

        <local:GenericType BaseType="{x:Type TypeName=coll:List`1}" 
                           InnerTypes="{StaticResource TypeParams}"
                           x:Key="ListOfInts" />

        <x:Array Type="{x:Type sys:Type}" 
                 x:Key="DictionaryParams">
            <x:Type TypeName="sys:Int32" />
            <local:GenericType BaseType="{x:Type TypeName=coll:List`1}" 
                               InnerTypes="{StaticResource TypeParams}" />
        </x:Array>

        <local:GenericType BaseType="{x:Type TypeName=coll:Dictionary`2}"
                           InnerTypes="{StaticResource DictionaryParams}"
                           x:Key="DictionaryOfIntsToListOfInts" />
    </Grid.Resources>

There's a few key ideas here:

  • A generic type has to be specified using the standard ` notation. So, System.Collections.Generic.List<> is System.Collections.Generic.List`1. The character ` indicates that the type is generic and the number after it indicates the number of generic parameters the type has.
  • The x:Type markup extension is able to retrieve these base generic types quite easily.
  • The generic parameter types are passed as an array of Type objects. This array is then passed into the MakeGenericType(...) call.
16
ответ дан 6 December 2019 в 08:43
поделиться

This is not supported in WPF 3.x out of the box (I think it may be in 4.0, but I'm not sure); but it's easy to set up with a markup extension.

First, you need to create a markup extension class that takes the type parameter as a constructor argument:

public class MyClassOf : MarkupExtension
{
  private readonly Type _of;

  public MyClassOf(Type of)
  {
    _of = of;
  }

  public override object ProvideValue(IServiceProvider serviceProvider)
  {
    return typeof(MyClass<>).MakeGenericType(_of);
  }
}

Now you use this markup extension in place of the x:Type extension:

<HierarchicalDataTemplate DataType="{local:MyClassOf {x:Type MyObject}}" />

Needless to say, this can be generalised to allow instantiation of arbitrary generic types; I haven't shown this because it adds a wee bit more complexity.

4
ответ дан 6 December 2019 в 08:43
поделиться
Другие вопросы по тегам:

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