16

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?

Anatoliy Nikolaev
  • 22,370
  • 15
  • 69
  • 68
Tony Vitabile
  • 8,298
  • 15
  • 67
  • 123
  • Are the other two cases especially the case `IsInLiveMode=true` and `IsSelected=false` working correctly? – nemesv Aug 28 '12 at 13:34
  • 1
    I did a quick test with your triggers and they work fine, however the background color does not always get inherited by the `DataGridCell`. The easiest way to change that is to use an implicit style for `DataGridCell` that sets the `Background` to `Transparent` – Rachel Aug 28 '12 at 13:47

2 Answers2

20

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>
nemesv
  • 138,284
  • 16
  • 416
  • 359
  • nemesv: Thanks, that at least doesn't throw any errors. There is still a problem. Please look at my edits to my original question. – Tony Vitabile Aug 28 '12 at 13:29
8

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" />
Rachel
  • 130,264
  • 66
  • 304
  • 490
  • Rachel: I wish I could check off yours and @nemesv's answers as the correct answer, because you're both right. But nemesv did answer first, so he gets the checkmark. – Tony Vitabile Aug 28 '12 at 13:28
  • @TonyVitabile That's fine, I think his answer is better anyways because of the MSDN links, and already gave him a +1 for it :) – Rachel Aug 28 '12 at 13:38