14

Вопрос по mvvm-light, xaml, mvvm, wpf – Как ссылаться на универсальный тип в атрибуте DataType DataTemplate?

У меня есть ViewModel, определенный следующим образом:

 public class LocationTreeViewModel<TTree> : 
               ObservableCollection<TTree>, INotifyPropertyChanged
                                                    where TTree : TreeBase<TTree>

Я хочу сослаться на него в атрибуте DataType DataTemplate в XAML. Как я могу это сделать?

  • Error: User Rate Limit Exceededbuilt a generic wrapper, see my answer expounding on this

    от
  • Error: User Rate Limit Exceededx:TypeArgumentsError: User Rate Limit Exceededx:Type.

    от
  • Error: User Rate Limit ExceededDataTemplateError: User Rate Limit ExceededDataTypeError: User Rate Limit Exceededx:TypeError: User Rate Limit Exceeded@ColinE's answerError: User Rate Limit Exceeded

    от
  • Error: User Rate Limit ExceededDataTypeError: User Rate Limit ExceededDataTemplateError: User Rate Limit Exceeded

    от
  • Error: User Rate Limit Exceeded

    от Gypsy
  • Error: User Rate Limit Exceeded

    от
  • Error: User Rate Limit Exceeded

    от
  • Error: User Rate Limit Exceeded

    от
  • возможный дубликатCan I specify a generic type in XAML?

    от franssu
5 ответов
  • -3

    Единственный способ сделать это - использовать

    MarkupExtensions.

    public class GenericType : MarkupExtension
    {
         private readonly Type _of;
         public GenericType(Type of)
         {
             _of = of;
         }
         public override object ProvideValue(IServiceProvider serviceProvider)
         {
             return typeof(LocationTreeViewModel<>).MakeGenericType(_of);
         }
    }
    

    И чтобы использовать это, мне просто нужно сделать это:

    <DataTemplate DataType="{app:GenericType app:TreeBaseClass}">
    

  • 3

    В XAML 2006 это не поддерживается. Вы можете

    однако, свернуть свой собственный, если вы хотите иметь эту функцию.

    Эта ссылка имеет хороший учебник по созданию расширений разметки.

    Использование было бы так:

    <Grid xmlns:ext="clr-namespace:CustomMarkupExtensions">
      <TextBlock Text="{ext:GenericType FooLocationTreeViewModel(Of Foo)}" />
    </Grid>
    

    Вы должны выбрать и реализовать синтаксис, хотя. Я предлагаю использовать нотацию VB, поскольку она не будет мешать, как нотация C # с & lt; и & gt ;.

  • 0

    Поддержка расширения разметки {x

    Type} позволяет указывать аргументы универсального типа в виде списка через запятую в скобках.

    Вот пример:

    <UserControl x:Class="Test"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:generic="clr-namespace:System.Collections.Generic;assembly=mscorlib"
            xmlns:sys="clr-namespace:System;assembly=mscorlib">
        <UserControl.Resources>
            <DataTemplate DataType="{x:Type generic:List(sys:Int64)}">
                <TextBlock Text="{Binding Count}"/>
            </DataTemplate>
        </UserControl.Resources>
    </UserControl>
    

    Я использую .Net 4.5 на VS 2015, поэтому ваш пробег может отличаться.

  • -3

    Немного улучшенная версия MarkupExtension

    работа для классов до 3 общих параметров.

      public class GenericTypeExtension : MarkupExtension
      {
        public GenericTypeExtension()
        {
    
        }
        public GenericTypeExtension(string baseTypeName_, Type genericType1_, Type genericType2_, Type genericType3_)
        {
          BaseTypeName = baseTypeName_;
          GenericType1 = genericType1_;
          GenericType2 = genericType2_;
          GenericType3 = genericType3_;
        }
        public string BaseTypeName { get; set; }
        public string BaseTypeAssemblyName { get; set; }
        public Type GenericType1 { get; set; }
        public Type GenericType2 { get; set; }
        public Type GenericType3 { get; set; }
    
        public override object ProvideValue(IServiceProvider serviceProvider_)
        {
          var list = new List<Type>();
          if (GenericType1 != null)
          {
            list.Add(GenericType1);
          }
          if (GenericType2 != null)
          {
            list.Add(GenericType2);
          }
          if (GenericType3 != null)
          {
            list.Add(GenericType3);
          }
    
          var type = Type.GetType(string.Format("{0}`{1}, {2}", BaseTypeName, list.Count, BaseTypeAssemblyName));
          if (type != null)
          {
            return type.MakeGenericType(list.ToArray());
          }
          return null;
        }
    
      }
    

  • 9

    Нет

    вы не можете выразить универсальный тип в XAML. Вам нужно будет создать конкретный тип, который расширит ваш общий ...

    public class FooLocationTreeViewModel : LocationTreeViewModel<Foo>
    {
    }