How to have alternative background color of the selected rows on WPF DataGrid via MultiDataTrigger

638 views Asked by At

I would like to display the odd vs. even selected rows with different background color (gray) in a WPF DataGrid. I already use the RowBackground="#DDD", AlternatingRowBackground="#EEE" and AlternationCount=2 properties withing DataGrid itself to alternate the color of non-selected rows.

I've already browsed many threads on StackOverflow, but can't find why the Style.Triggers has no effect. I use this attached property to determine whether it is an odd or even row.

<DataGrid.RowStyle>
    <Style TargetType="DataGridRow">
        
        <!-- Changes the row style template to have more advanced "borders" (dotted, dashed, etc.) based on value converters -->
        <Setter Property="Template">
            <!-- ... -->
        </Setter>
        
        <!-- Changes the background color of odd rows (will do the same for even one with a slightly different color) -->
        <Style.Triggers>
            <MultiDataTrigger>
                <MultiDataTrigger.Conditions>
                    <Condition Binding="{Binding IsSelected, RelativeSource={RelativeSource Self}}"
                               Value="True"/>
                    <Condition Binding="{Binding (behaviors:DataGridBehavior.IsOddRow), RelativeSource={RelativeSource Self}}"
                               Value="True"/>
                </MultiDataTrigger.Conditions>
                <MultiDataTrigger.Setters>
                    <Setter Property="Background"
                            Value="LightYellow"/>
                </MultiDataTrigger.Setters>
            </MultiDataTrigger>

            <!-- Same principle for even rows -->
            <!-- ... -->

        </Style.Triggers>
    </Style>
</DataGrid.RowStyle>

Same (no) effect if I use only one Condition in the MutliDataTrigger.

Thanks for any insights :-)

1

There are 1 answers

1
thatguy On BEST ANSWER

You do not have to use a custom behavior for this, you can use the built-in alternation mechanism.

<DataGrid AlternationCount="2"
          ...>
   <!-- ...other properties -->
</DataGrid>

Create a style for DataGridRow with triggers for the IsSelected and AlternationIndex attached property. Note, that we have to set the row background color and the alternating background color here, too, because setting the RowBackground and AlternatingRowBackground on DataGrid will overwrite the background values defined in the style and the selection highlighting would not work, so remove them from DataGrid.

<DataGrid.RowStyle>
   <Style TargetType="{x:Type DataGridRow}" BasedOn="{StaticResource {x:Type DataGridRow}}">

      <!-- Changes the row style template to have more advanced "borders" (dotted, dashed, etc.) based on value converters -->
      <Setter Property="Template">
         <!-- ... -->
      </Setter>

      <!-- Part for odd rows. -->
      <Style.Triggers>
         <MultiTrigger>
            <MultiTrigger.Conditions>
               <Condition Property="IsSelected"
                          Value="False"/>
               <Condition Property="AlternationIndex"
                          Value="1"/>
            </MultiTrigger.Conditions>
            <MultiTrigger.Setters>
               <Setter Property="Background"
                       Value="#EEE"/>
            </MultiTrigger.Setters>
         </MultiTrigger>

         <MultiTrigger>
            <MultiTrigger.Conditions>
               <Condition Property="IsSelected"
                          Value="True"/>
               <Condition Property="AlternationIndex"
                          Value="1"/>
            </MultiTrigger.Conditions>
            <MultiTrigger.Setters>
               <Setter Property="Background"
                       Value="Yellow"/>
            </MultiTrigger.Setters>
         </MultiTrigger>

         <!-- Part for even rows. -->

         <MultiTrigger>
            <MultiTrigger.Conditions>
               <Condition Property="IsSelected"
                          Value="False"/>
               <Condition Property="AlternationIndex"
                          Value="0"/>
            </MultiTrigger.Conditions>
            <MultiTrigger.Setters>
               <Setter Property="Background"
                       Value="#DDD"/>
            </MultiTrigger.Setters>
         </MultiTrigger>

         <MultiTrigger>
            <MultiTrigger.Conditions>
               <Condition Property="IsSelected"
                          Value="True"/>
               <Condition Property="AlternationIndex"
                          Value="0"/>
            </MultiTrigger.Conditions>
            <MultiTrigger.Setters>
               <Setter Property="Background"
                       Value="LightYellow"/>
            </MultiTrigger.Setters>
         </MultiTrigger>

      </Style.Triggers>

   </Style>
</DataGrid.RowStyle>

Since a DataGridCell is a child of a DataGridRow, the selection colors defined there will occlude the row colors. To avoid creating the same style for DataGridCell, too, we set its background transparent when it is selected.

<DataGrid.CellStyle>
   <Style TargetType="{x:Type DataGridCell}" BasedOn="{StaticResource {x:Type DataGridCell}}">
      <Style.Triggers>
         <DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource AncestorType={x:Type DataGridRow}}}"
                      Value="True">
            <Setter Property="Background"
                    Value="Transparent"/>
         </DataTrigger>
      </Style.Triggers>
   </Style>
</DataGrid.CellStyle>