次のように定義された ViewModel があります。
public class LocationTreeViewModel<TTree> :
ObservableCollection<TTree>, INotifyPropertyChanged
TTree : TreeBase<TTree>
XAMLDataType
のaの属性で参照したい。DataTemplate
どうやってやるの?
次のように定義された ViewModel があります。
public class LocationTreeViewModel<TTree> :
ObservableCollection<TTree>, INotifyPropertyChanged
TTree : TreeBase<TTree>
XAMLDataType
のaの属性で参照したい。DataTemplate
どうやってやるの?
いいえ、XAML でジェネリック型を表現することはできません。ジェネリック型を拡張する具象型を作成する必要があります...
public class FooLocationTreeViewModel : LocationTreeViewModel<Foo>
{
}
XAML 2006 では、これはサポートされていません。ただし、この機能が必要な場合は、独自のロールを作成できます。
このリンクには、マークアップ拡張機能の作成に関する優れたチュートリアルがあります。
使用法は次のようになります。
<Grid xmlns:ext="clr-namespace:CustomMarkupExtensions">
<TextBlock Text="{ext:GenericType FooLocationTreeViewModel(Of Foo)}" />
</Grid>
ただし、構文を選択して実装する必要があります。C# 表記法が < および > で行うように干渉しないため、VB 表記法をお勧めします。
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;
}
}
これを行う唯一の方法は、を使用すること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}">