2012-04-04 4 views
13

Ho un ViewModel definita in questo modo:Come fare riferimento a un tipo generico nell'attributo DataType di un DataTemplate?

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

voglio fare riferimento a esso nel l'attributo DataType di un DataTemplate in XAML. Come lo posso fare?

+0

possibile duplicato del [Posso specificare un tipo generico in XAML?] (Http://stackoverflow.com/questions/185349/can-i-specify-a-generic-type-in-xaml) – franssu

risposta

-2

L'unico modo per farlo è utilizzare 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); 
    } 
} 

E per usarlo ho solo bisogno di fare questo:

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

È una soluzione scadente poiché è accoppiata alla classe LocationTreeViewModel .. – franssu

+0

@franssu: Grazie per il tuo commento, ma non capisco cosa intendi? Non volevo usarlo per ogni classe generica, non lo uso pensate che sia persino possibile! Hai una soluzione migliore? –

+1

-1: Sfortunatamente questo fa scattare un errore MC; 'DataType' di DataTemplate' può accettare solo un set predefinito di estensioni [come' x: Type']. Succhiare [la risposta di ColinE] (http://stackoverflow.com/a/10005490/11635) è stata la mia conclusione –

8

No, non è possibile esprimere un tipo generico in XAML. Si dovrà creare un tipo di cemento che si estende il vostro generico ...

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

Ho usato questa tecnica con successo ma alla fine [ho creato un wrapper generico, vedi la mia risposta su questo argomento] (http://stackoverflow.com/a/33827448/11635) –

3

In XAML 2006 questo non è supportato. Tuttavia, è possibile eseguire il rollover se si desidera avere questa funzionalità.

This link ha un bel tutorial sulla creazione di estensioni di markup.

Uso sarebbe come questo:

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

dovete scegliere e implementare la sintassi però. Suggerisco la notazione VB poiché non interferirà come fa la notazione C# con < e>.

+2

non funzionerà come il bit "DataType' di un' DataTemplate' non consente estensioni di markup –

-1

Leggermente migliorata versione di MarkupExtension, lavoro per le classi fino 3 parametri generici.

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

Questo non risponde all'OP - nessun utilizzo per i datatemplates –