WPF Trigger based on Object Type
-
22-07-2019 - |
Question
Is there a way to do a comparison on object type for a trigger?
<DataTrigger Binding="{Binding SelectedItem}" Value="SelectedItem's Type">
</DataTrigger>
Background: I have a Toolbar and I want to Hide button's depending on what subclass is currently set to the selected item object.
Thanks
Solution
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.
OTHER TIPS
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();
}
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>
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
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
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.