Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DataTriggerBehavior Doesn't Work With Enum?

I'm trying to use a DataTriggerBehavior from the Behaviors SDK. But it doesn't seem to work with enums... or else I'm doing something wrong.

You can assume that the DataContext for these examples is something like this (INotifyPropertyChanged is implemented, but I'm not going to show it here):

public class MyDataClass
{
    public MyEnum ItemCommand { get; set; }
    public string ItemCommandString { get; set; }
}

public enum MyEnum
{
    EnumValue1
}

_Button.DataContext = new MyDataClass() { ItemCommand = MyEnum.EnumValue1, 
                                          ItemCommandString = "EnumValue1" };

Here is the code that doesn't work (trying to specify an enum value and check against the ItemCommand enum property):

<ToggleButton x:Name="_Button">
    <Interactivity:Interaction.Behaviors>
        <Core:DataTriggerBehavior Binding="{Binding ItemCommand}" 
                                  Value="EnumValue1">
            <Core:ChangePropertyAction PropertyName="Command" 
                                       TargetObject="{Binding ElementName=_Button}"
                                       Value="{x:Null}">
            </Core:ChangePropertyAction>
        </Core:DataTriggerBehavior>
    </Interactivity:Interaction.Behaviors>
</ToggleButton>

and this code (checking against an enum resource) also does not work:

<UserControl.Resources>
    <local:MyEnum x:Key="_MyEnumValue">EnumValue1</local:MyEnum>
</UserControl.Resources>

<ToggleButton x:Name="_Button">
    <Interactivity:Interaction.Behaviors>
        <Core:DataTriggerBehavior Binding="{Binding ItemCommand}" 
                                  Value="{StaticResource _MyEnumValue}">
            <Core:ChangePropertyAction PropertyName="Command" 
                                       TargetObject="{Binding ElementName=_Button}"
                                       Value="{x:Null}">
            </Core:ChangePropertyAction>
        </Core:DataTriggerBehavior>
    </Interactivity:Interaction.Behaviors>
</ToggleButton>

whereas this code (checking against a string) does work:

<ToggleButton x:Name="_Button">
    <Interactivity:Interaction.Behaviors>
        <Core:DataTriggerBehavior Binding="{Binding ItemCommandString}" 
                                  Value="EnumValue1">
            <Core:ChangePropertyAction PropertyName="Command" 
                                       TargetObject="{Binding ElementName=_Button}"
                                       Value="{x:Null}">
            </Core:ChangePropertyAction>
        </Core:DataTriggerBehavior>
    </Interactivity:Interaction.Behaviors>
</ToggleButton>

What is the correct way to specify the enum value in the DataTriggerBehavior Value property so that this will work?

like image 455
Tim Avatar asked Oct 31 '22 23:10

Tim


2 Answers

you can write a Converter:

 public class MyEnumConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, string language)
        {
            MyEnum myEnumValue = (MyEnum)value;
            return myEnumValue.ToString();
        }

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

And use it in XAML:

<ToggleButton x:Name="_Button">
    <Interactivity:Interaction.Behaviors>
        <Core:DataTriggerBehavior Binding="{Binding ItemCommand, Converter={StaticResource MyEnumConverter}}" 
                                  Value="EnumValue1">
            <Core:ChangePropertyAction PropertyName="Command" 
                                       TargetObject="{Binding ElementName=_Button}"
                                       Value="{x:Null}">
            </Core:ChangePropertyAction>
        </Core:DataTriggerBehavior>
    </Interactivity:Interaction.Behaviors>
</ToggleButton>

Or bind direct to the string as in your sample. Unfortunately DataTriggerBehavior in WinRT is worse that DataTrigger in Windows Phone 8

like image 163
Валера Галанин Avatar answered Nov 09 '22 05:11

Валера Галанин


I was investigating this issue and narrowed the problem down to TypeConverterHelper class. TypeConverterHelper source

Apparently it doesn’t account for enum types and falls back to some logic which recreates the xaml string for the enum. Parses it as ContentControl and passes back its content. Unfortunately during this step it loses the enum type information and subsequent type casting is not valid.

If you are working with sources and not just NuGet package you can fix it yourself. Just add another overload of Convert method to TypeConverterHelper:

public static Object Convert(string value, Type destinationType)
{
    var typeInfo = destinationType.GetTypeInfo();

    if (typeInfo.IsEnum)
        return Enum.Parse(destinationType, value);

    return Convert(value, destinationType.FullName);
}

And of course change the call in DataTriggerBehavior Compare method from:

rightOperand = TypeConverterHelper.Convert(rightOperand.ToString(), leftOperand.GetType().FullName);

to:

rightOperand = TypeConverterHelper.Convert(rightOperand.ToString(), leftOperand.GetType());
like image 29
Matej Pavlů Avatar answered Nov 09 '22 07:11

Matej Pavlů