2009-10-30 20 views
34

Esiste un modo per eseguire un confronto sul tipo di oggetto per un trigger?Trigger WPF basato sul tipo di oggetto

<DataTrigger Binding="{Binding SelectedItem}" Value="SelectedItem's Type"> 
</DataTrigger> 

Background: ho una barra degli strumenti e voglio nascondere il pulsante di seconda di ciò che sottoclasse è attualmente impostato all'oggetto voce selezionata.

Grazie

risposta

29

Perché non basta utilizzare un convertitore che prende un oggetto e restituisce una stringa del tipo di oggetto?

Binding="{Binding SelectedItem, Converter={StaticResource ObjectToTypeString}}"

e definire il convertitore come:

public class ObjectToTypeStringConverter : IValueConverter 
{ 
    public object Convert(
    object value, Type targetType, 
    object parameter, System.Globalization.CultureInfo culture) 
    { 
     return value.GetType().Name;    
    } 

    public object ConvertBack(
    object value, Type targetType, 
    object parameter, System.Globalization.CultureInfo culture) 
    { 
     // I don't think you'll need this 
     throw new Exception("Can't convert back"); 
    } 
} 

Avrete bisogno di dichiarare la risorsa statica qualche parte nel vostro XAML:

<Window.Resources> 
    <convs:ObjectToTypeStringConverter x:Key="ObjectToTypeString" /> 
</Window.Resources> 

Dove 'convs' in questo caso è lo spazio dei nomi di dove si trova il convertitore.

Spero che questo aiuti.

+10

+1 per l'idea generale, tuttavia il convertitore dovrebbe restituire l'oggetto Type piuttosto che il suo nome ... –

+2

Potrebbe funzionare? Il runtime non dovrebbe confrontare qualcosa di tipo String a qualcosa di tipo Type? So che gestisce la conversione/confronto della maggior parte dei tipi di valore, ma non ha familiarità con il modo in cui gestisce altri confronti di tipo. – AndyG

+5

Sì, funzionerebbe, devi solo usare l'estensione di markup {x: Type} nel valore di DataTrigger. –

4

L'utilizzo di un convertitore come suggerito da AndyG è una buona opzione. In alternativa, è possibile utilizzare anche un diverso DataTemplate per ciascun tipo di destinazione. WPF sceglierà automaticamente lo DataTemplate che corrisponde al tipo di oggetto

+0

Ma interesserà anche ogni sottoelemento di quel tipo di dati – Staeff

42

Questo è basato sulla risposta di @ AndyG, ma è un po 'più sicuro perché è fortemente digitato.

Implementare un IValueConverter nome DataTypeConverter, che accetta un oggetto e restituisce il tipo (come System.Type):

public class DataTypeConverter:IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, 
     CultureInfo culture) 
    { 
     return value.GetType(); 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, 
     CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 
} 

Cambia la tua DataTrigger Per utilizzare il convertitore, e impostare il valore per il tipo:

<DataTrigger Binding="{Binding SelectedItem, 
     Converter={StaticResource DataTypeConverter}}" 
     Value="{x:Type local:MyType}"> 
... 
</DataTrigger> 

Declare DataTypeConverter nelle risorse:

<UserControl.Resources> 
    <v:DataTypeConverter x:Key="DataTypeConverter"></v:DataTypeConverter> 
</UserControl.Resources> 
+1

Questo non funziona per me. Ricevo una XamlParseException se provo a utilizzare un'estensione di markup in DataTrigger.Value, quindi ho appena usato il metodo di confronto delle stringhe. Vedi qui: http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/14cbdb99-fd33-4ad0-8b1b-a0139c7fbf95/ – RobJohnson

+3

Controllare meglio se il valore è nullo prima di provare a GetType(). valore di ritorno! = null? value.GetType(): null; – Viv

+0

'Binding = "{Binding SelectedItem}" Converter = {StaticResource DataTypeConverter}} "'' dovrebbe essere Binding ="{Binding SelectedItem, convertitore = {StaticResource DataTypeConverter}}" ' – Firo

3

Non un grilletto ma questo ha funzionato per me. (Il trigger-approccio non ha fatto in quanto non in grado di creare una casella di controllo per una stringa Questo è più o meno Thomas Levesque's suggestion.)

utilizzando:

xmlns:mscorlib="clr-namespace:System;assembly=mscorlib" 

Una casella di controllo o TextBox a seconda del tipo:

<ContentPresenter Content="{TemplateBinding SelectedItem}"> 
     <ContentPresenter.Resources> 
       <DataTemplate DataType="{x:Type mscorlib:Boolean}"> 
        <CheckBox Height="25" Width="25" HorizontalAlignment="Left" IsChecked="{Binding Path=.}"/> 
       </DataTemplate> 
        <DataTemplate DataType="{x:Type mscorlib:String}"> 
        <TextBox Height="25" Width="200" HorizontalAlignment="Left" Text="{Binding Path=.}"/> 
       </DataTemplate> 
     </ContentPresenter.Resources> 
</ContentPresenter> 

Nota: per soluzione di Greg Sansom si sia avuto modo di restituire il tipo String o utilizzare mscorlib come sopra

Problemi correlati