Search code examples
.netwpfmvvmdatatriggermultidatatrigger

MultiDataTrigger is firing if only one condition is met


in my UserControl I have three ComboBoxes which all have to be selected before the save button is enabled. I defined a MultiDataTrigger with Bindings to my ViewModel Properties which are set to null initially. So when the control is loaded the button is disabled as expected but as soon as one of the ComboBoxes is selected the button will be enabled. As I understood all conditions of a MultiDataTrigger have to be met in order for it to fire?

Here's my Button Style:

        <Style x:Key="saveButton" TargetType="{x:Type Button}">
        <Style.Triggers>
            <MultiDataTrigger>
                <MultiDataTrigger.Conditions>
                    <Condition Binding="{Binding Path=CurrentSpeech.Room, Converter={StaticResource nullToBoolConverter}}" Value="true" />
                    <Condition Binding="{Binding Path=CurrentSpeech.Speaker, Converter={StaticResource nullToBoolConverter}}" Value="true" />
                    <Condition Binding="{Binding Path=CurrentSpeech.Track, Converter={StaticResource nullToBoolConverter}}" Value="true" />
                </MultiDataTrigger.Conditions>
                <Setter Property="Button.IsEnabled" Value="False" />
            </MultiDataTrigger>
        </Style.Triggers>
    </Style>

My ComboBoxes:

            <ComboBox Margin="3" Grid.Row="4" Grid.Column="1" ItemsSource="{Binding Path=Rooms, Mode=OneWay}"
                      SelectedItem="{Binding Path=CurrentSpeech.Room, Mode=TwoWay}" DisplayMemberPath="Name"/>
            <ComboBox Margin="3" Grid.Row="5" Grid.Column="1" ItemsSource="{Binding Path=Tracks, Mode=OneWay}"
                      SelectedItem="{Binding Path=CurrentSpeech.Track, Mode=TwoWay}" DisplayMemberPath="Title"/>
            <ComboBox Margin="3" Grid.Row="6" Grid.Column="1" ItemsSource="{Binding Path=Speakers, Mode=OneWay}" 
                      SelectedItem="{Binding Path=CurrentSpeech.Speaker, Mode=TwoWay}" DisplayMemberPath="Name"/>

My Button:

                <Button Style="{StaticResource saveButton}" Margin="3" Grid.Row="9" Grid.Column="1" Command="{Binding Path=CurrentSpeech.SaveCommand}" Width="150" HorizontalAlignment="Right" Content="Speichern"/>

And my Converter:

    [ValueConversion(typeof(object), typeof(bool))]
public class NullToBoolConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        bool result = value == null ? true : false;
        if (parameter != null)
            return !result;
        return result;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value;
    }
}

Thanks, Paxx


Solution

  • The trigger seems to work fine, it's just your logic that is not correct.

    As it works now, the trigger will be activated when the Room, Speaker and Track properties are all null. That happens when the program starts, since nothing is selected in either of the ComboBoxes.

    So all 3 conditions are met, and the trigger disables the Button.

    When you then select something in the Rooms combobox, the first condition in the trigger is no longer met, since the ValueConverter now returns false for that binding, so the trigger is disabled and this causes the button to be enabled.

    So to fix this issue, you should disable the Button initially, and only set it enabled in the trigger, when the converters return false for all bindings (when the 3 properties are NOT null).

    <Style x:Key="saveButton" TargetType="{x:Type Button}">
        <Setter Property="IsEnabled" Value="False"/>
        <Style.Triggers>
            <MultiDataTrigger>
                <MultiDataTrigger.Conditions>
                    <Condition Binding="{Binding Path=Room, Converter={StaticResource nullToBoolConverter}}" Value="false" />
                    <Condition Binding="{Binding Path=Speaker, Converter={StaticResource nullToBoolConverter}}" Value="false" />
                    <Condition Binding="{Binding Path=Track, Converter={StaticResource nullToBoolConverter}}" Value="false" />
                </MultiDataTrigger.Conditions>
                <Setter Property="Button.IsEnabled" Value="True" />
            </MultiDataTrigger>
        </Style.Triggers>
    </Style>