2012-04-04 10 views
13

que tienen un modelo de vista se define así:¿Cómo hacer referencia a un tipo genérico en el atributo DataType de una plantilla de datos?

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

quiero hacer referencia a ella en el atributo de tipo de datos de un DataTemplate en XAML. ¿Cómo puedo hacer eso?

+0

posible duplicado de [¿Puedo especificar un tipo genérico en XAML?] (Http://stackoverflow.com/questions/185349/can-i-specify-a-generic-type-in-xaml) – franssu

Respuesta

-2

La única forma en que podría hacer esto es usar 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); 
    } 
} 

Y para usarlo sólo hay que hacer esto:

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

Es una solución deficiente ya que está acoplado a la clase LocationTreeViewModel .. – franssu

+0

@franssu: Gracias por su comentario, pero no entiendo lo que quiere decir? No quise utilizar esto para cada clase genérica, no me gusta ¡No creo que sea posible! ¿Tiene una mejor solución? –

+1

-1: Desafortunadamente esto desencadena un error de MC; 'DataType' de DataTemplate' solo puede aceptar un conjunto predefinido de extensiones [como' x: Type']. Suck up [@ ColinE's answer] (http://stackoverflow.com/a/10005490/11635) fue mi conclusión –

8

No, no puede expresar un tipo de genéricos en XAML. Deberá crear un tipo concreto que amplíe el genérico ...

public class FooLocationTreeViewModel : LocationTreeViewModel<Foo> 
{ 
} 
+0

Utilicé esta técnica con éxito, pero en última instancia [construí un contenedor genérico, veré mi respuesta exponiendo esto] (http://stackoverflow.com/a/33827448/11635) –

3

En XAML 2006 esto no es compatible. Sin embargo, puede hacer las suyas si quiere tener esta funcionalidad.

This link tiene un buen tutorial sobre la creación de extensiones de marcado.

uso sería así:

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

usted tiene que elegir e implementar la sintaxis sin embargo. Sugiero la notación VB ya que no interferirá como lo hace la notación C# con < y>.

+2

no funcionará como el bit 'DataType' de' DataTemplate' no permite las extensiones de marcado –

-1

versión ligeramente mejorada de MarkupExtension, el trabajo para las clases hasta 3 parámetros genéricos.

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; 
    } 

    } 
+0

Esto no responde al OP - no se usa para datatemplates –

Cuestiones relacionadas