Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the right way to trigger on multiple conditions in a WPF Style

My WPF application has a DataGrid control in it. I have a default custom style for the DataGridRow class which works well. However, for this one particular DataGrid on this one particular screen, I need a different custom style.

The Items in each row have a bool property that, when set, I want to display that row with a different foreground and background color. However, when the row is selected AND when that property is set, I want a different foreground and background color to show that it's selected AND the property is set to true.

Here's what I've tried:

<Style TargetType="DataGridRow" x:Key="CameraStyle">
    <Setter Property="Foreground" Value="{DynamicResource TextForeground}" />
    <Setter Property="Background" Value="{DynamicResource DataBackground}" />
    <Style.Triggers>
        <MultiDataTrigger>
            <MultiDataTrigger.Conditions>
                <Condition Property="IsSelected" Value="False" />
                <Condition Binding="{Binding Path=IsInLiveMode}" Value="True" />
            </MultiDataTrigger.Conditions>
            <Setter Property="Foreground" Value="Red" />
            <Setter Property="Background" Value="Yellow" />
        </MultiDataTrigger>
        <MultiDataTrigger>
            <MultiDataTrigger.Conditions>
                <Condition Property="IsSelected" Value="True" />
                <Condition Binding="{Binding Path=IsInLiveMode}" Value="True" />
            </MultiDataTrigger.Conditions>
            <Setter Property="Background"  Value="DarkOrange" />
            <Setter Property="BorderBrush" Value="{DynamicResource DataBorder}" />
            <Setter Property="Foreground"  Value="DarkRed" />
        </MultiDataTrigger>
    </Style.Triggers>
</Style>

This gives me a "Binding must be non-null" error, which I think is happening because there is no Binding property on the first condition in the MultiDataTrigger.

What is the correct way to write this in XAML?

EDIT:

After trying nemesv's & Rachel's answer, the code now compiles and runs. However, the colors I've chosen for the IsSelected = true and IsInLiveMode = true case are not showing up. Here's what I have now:

    <Style TargetType="DataGridRow" x:Key="CameraStyle">
        <Setter Property="Background" Value="{DynamicResource DataBackground}" />
        <Setter Property="Foreground" Value="{DynamicResource TextForeground}" />
        <Style.Triggers>
            <MultiDataTrigger>
                <MultiDataTrigger.Conditions>
                    <Condition Binding="{Binding Path=IsSelected, RelativeSource={RelativeSource Self}}" Value="False" />
                    <Condition Binding="{Binding Path=IsInLiveMode}" Value="True" />
                </MultiDataTrigger.Conditions>
                <Setter Property="Background" Value="Yellow" />
                <Setter Property="Foreground" Value="Red" />
            </MultiDataTrigger>
            <MultiDataTrigger>
                <MultiDataTrigger.Conditions>
                    <Condition Binding="{Binding Path=IsSelected, RelativeSource={RelativeSource Self}}" Value="True" />
                    <Condition Binding="{Binding Path=IsInLiveMode}" Value="False" />
                </MultiDataTrigger.Conditions>
                <Setter Property="Background"  Value="{DynamicResource DataBackgroundSelected}" />
                <Setter Property="BorderBrush" Value="{DynamicResource DataBorder}" />
                <Setter Property="Foreground"  Value="{DynamicResource DataForegroundSelected}" />
            </MultiDataTrigger>
            <MultiDataTrigger>
                <MultiDataTrigger.Conditions>
                    <Condition Binding="{Binding Path=IsSelected, RelativeSource={RelativeSource Self}}" Value="True" />
                    <Condition Binding="{Binding Path=IsInLiveMode}" Value="True" />
                </MultiDataTrigger.Conditions>
                <Setter Property="Background"  Value="DarkOrange" />
                <Setter Property="BorderBrush" Value="{DynamicResource DataBorder}" />
                <Setter Property="Foreground"  Value="DarkRed" />
            </MultiDataTrigger>
        </Style.Triggers>
    </Style>

Any ideas on why the case in question isn't working?

like image 282
Tony Vitabile Avatar asked Aug 28 '12 13:08

Tony Vitabile


People also ask

What is multi trigger in WPF?

XAML Values MultiTrigger enables you to set property values or start actions based on a collection of Condition objects. A condition is met when the value of the property (specified by the Property property of the Condition class) of the element matches the specified Value.

What is trigger and how many types of triggers in WPF?

Triggers are used to create visual effects on controls and framework elements. Triggers are parts of styles and are always defined inside a style. Basically, there are 3 types of triggers, they are: Property Trigger.

How many types of triggers are there in WPF?

There are five types of triggers supported by WPF; they are: Property Trigger. Data Trigger. MultiTrigger.


2 Answers

Your assumptution is correct regarding the missing binding.

From MSDN MultiDataTrigger.Conditions:

For a MultiDataTrigger, each condition in the collection must set both the Binding and Value properties.

You can solve this using RelativeSource Self to refer yourself in the binding:

<MultiDataTrigger.Conditions>
    <Condition Binding="{Binding RelativeSource={RelativeSource Self},
         Path=IsSelected}" Value="True" />
    <Condition Binding="{Binding Path=IsInLiveMode}" Value="True" />
</MultiDataTrigger.Conditions>
like image 82
nemesv Avatar answered Oct 06 '22 10:10

nemesv


You're using a MultiDataTrigger, which is still a DataTrigger and expects a binding

Switch Property="IsSelected" in your Condition to

<Condition Binding="{Binding IsSelected, RelativeSource={RelativeSource Self}}" 
           Value="True" />
like image 27
Rachel Avatar answered Oct 06 '22 10:10

Rachel