WPF Trigger based on Object Type

前端 未结 5 935
自闭症患者
自闭症患者 2020-12-13 17:27

Is there a way to do a comparison on object type for a trigger?




        
相关标签:
5条回答
  • 2020-12-13 18:06

    This is based on @AndyG's answer but is a bit safer because it's strongly typed.

    Implement an IValueConverter named DataTypeConverter, which accepts an object and returns its Type (as a System.Type):

    public class DataTypeConverter:IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, 
          CultureInfo culture)
        {
            return value?.GetType() ?? Binding.DoNothing;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter,
          CultureInfo culture)
        {
           throw new NotImplementedException();
        }
    }
    

    Change your DataTrigger to use the Converter, and set the value to the Type:

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

    Declare DataTypeConverter in the resources:

    <UserControl.Resources>
        <v:DataTypeConverter x:Key="DataTypeConverter"></v:DataTypeConverter>
    </UserControl.Resources>
    
    0 讨论(0)
  • 2020-12-13 18:07

    If you are in a position to modify the (base) type assigned to 'SelectedItem' by adding the property:

    public Type Type => this.GetType();
    

    Then you could use the DataTrigger in xaml like this:

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

    Advantage compared to AndyG's good answer is, that you do not have a magic string of your type in XAML, but have everything compile safe. Disadvantage: You need to modify your model - which might not always be possible.

    0 讨论(0)
  • 2020-12-13 18:13

    Using a converter as suggested by AndyG is a good option. Alternatively, you could also use a different DataTemplate for each target type. WPF will automatically pick the DataTemplate that matches the object type

    0 讨论(0)
  • 2020-12-13 18:18

    Not a trigger but this worked for me. (The trigger-approach didn't as it can't create a checkbox for a string. This is pretty much Thomas Levesque's suggestion)

    using:

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

      A CheckBox or TextBox depending on the 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>
    

    Note: for Greg Sansom's solution you either got to return the type as String or use mscorlib as above

    0 讨论(0)
  • 2020-12-13 18:26

    Why not just use a converter that takes an object and returns a string of the object type?

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

    and define the converter as:

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

    You'll need to declare the static resource somewhere in your xaml:

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

    Where 'convs' in this case is the namespace of where the converter is.

    Hope this helps.

    0 讨论(0)
提交回复
热议问题