web-dev-qa-db-fra.com

Déclencheur WPF basé sur le type d'objet

Y a-t-il un moyen de faire une comparaison sur le type d'objet pour un déclencheur?

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

Arrière-plan: J'ai une barre d'outils et je veux masquer le bouton en fonction de la sous-classe actuellement définie pour l'objet de l'élément sélectionné.

Merci

35
Exist

Pourquoi ne pas simplement utiliser un convertisseur qui prend un objet et retourne une chaîne du type d'objet?

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

et définissez le convertisseur comme:

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

Vous devrez déclarer la ressource statique quelque part dans votre xaml:

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

Où 'convs' dans ce cas est l'espace de noms de l'endroit où se trouve le convertisseur.

J'espère que cela t'aides.

31
AndyG

Ceci est basé sur la réponse de @ AndyG mais est un peu plus sûr car il est fortement typé.

Implémentez un IValueConverter nommé DataTypeConverter, qui accepte un objet et renvoie son type (sous la forme d'un 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();
    }
}

Changez votre DataTrigger pour utiliser le convertisseur et définissez la valeur sur Type:

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

Déclarez DataTypeConverter dans les ressources:

<UserControl.Resources>
    <v:DataTypeConverter x:Key="DataTypeConverter"></v:DataTypeConverter>
</UserControl.Resources>
44
Greg Sansom

Pas un déclencheur mais cela a fonctionné pour moi. (L'approche de déclenchement n'a pas fonctionné, car elle ne peut pas créer de case à cocher pour une chaîne. C'est assez bien suggestion de Thomas Levesque )

en utilisant:

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

Un CheckBox ou un TextBox selon le type:

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

Remarque: pour la solution de Greg Sansom, vous devez soit renvoyer le type String, soit utiliser mscorlib comme ci-dessus.

4
mYnDstrEAm

L'utilisation d'un convertisseur suggéré par AndyG est une bonne option. Vous pouvez également utiliser une variable DataTemplate différente pour chaque type de cible. WPF choisira automatiquement la DataTemplate qui correspond au type d'objet

4
Thomas Levesque

Si vous êtes en mesure de modifier le type (base) attribué à 'SelectedItem' en ajoutant la propriété:

public Type Type => this.GetType();

Ensuite, vous pouvez utiliser le DataTrigger dans xaml comme ceci:

<DataTrigger Binding="{Binding SelectedItem.Type}" Value="{x:Type local:MyClass}">
</DataTrigger>

L'avantage par rapport à la bonne réponse d'AndyG est que vous n'avez pas de chaîne magique de votre type en XAML, mais que tout est bien compilé. Inconvénient: vous devez modifier votre modèle, ce qui n’est pas toujours possible.

0
sam