Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF Datagrid trigger row colour based on value

Tags:

c#

wpf

datagrid

I have a WPF application that contains a datagrid. The datagrid is bound to my object OrderBlock which contains a List of type Orders.

<DataGrid DataContext="{Binding OrderBlock}"
              Name="dataGridOrdersGood" 
              ItemsSource="{Binding Orders}"

This works fine and displays nicely in my datagrid. There is one property (StatusGood) in my List though that I would like to display as a combobox where there can be only two values, "Send" or "Hold".

If the value in the combobox is "Hold" I would like the row to turn different colour. Ideally using a linear gradient going from silver to yellow. I have tried the code below - literally just trying to turn the row red for the moment but nothing happens. I can't see what is wrong with my code below. The trigger part is very close to the bottom of the code below. I'm new to WPF and struggling with it at the moment. The code below has mainly come from a very good post that can be found here, http://www.codeproject.com/Articles/586132/WPF-DataGrid-Custommization-using-Style-and-Templa

    <!-- Data grid formatting Grid Row template -->
    <Style x:Key="DG_Row" TargetType="{x:Type DataGridRow}">
        <Setter Property="Background" Value="LightGreen"/>
        <Setter Property="Opacity" Value="1"/>
        <Setter Property="Padding" Value="3,2,2,3"/>
        <Setter Property="Validation.ErrorTemplate" Value="{x:Null}"/>            
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type DataGridRow}">
                    <Border x:Name="DGR_Border"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}"
                            SnapsToDevicePixels="True">
                        <Border.Background>
                            <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
                                <GradientStop Offset="0" Color="Transparent"/>
                                <GradientStop Offset="1" Color="Silver"/>
                            </LinearGradientBrush>                                
                        </Border.Background>
                        <SelectiveScrollingGrid>
                            <SelectiveScrollingGrid.ColumnDefinitions>
                                <ColumnDefinition Width="Auto" />
                                <ColumnDefinition Width="*" />
                            </SelectiveScrollingGrid.ColumnDefinitions>
                            <SelectiveScrollingGrid.RowDefinitions>
                                <RowDefinition Height="20" />
                                <RowDefinition Height="Auto" />
                            </SelectiveScrollingGrid.RowDefinitions>
                            <DataGridCellsPresenter Grid.Column="1"
                                ItemsPanel="{TemplateBinding ItemsPanel}"
                                SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                            <DataGridDetailsPresenter Grid.Row="1"
                                Grid.Column="1"
                                SelectiveScrollingGrid.SelectiveScrollingOrientation="{Binding AreRowDetailsFrozen, ConverterParameter={x:Static SelectiveScrollingOrientation.Vertical},
                                  Converter={x:Static DataGrid.RowDetailsScrollingConverter},
                                  RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"
                                Visibility="{TemplateBinding DetailsVisibility}" />
                                                    <DataGridRowHeader Grid.RowSpan="2" SelectiveScrollingGrid.SelectiveScrollingOrientation="Vertical"
                                                        Visibility="{Binding HeadersVisibility, ConverterParameter={x:Static DataGridHeadersVisibility.Row},
                                                                        Converter={x:Static DataGrid.HeadersVisibilityConverter},
                            RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"/>
                        </SelectiveScrollingGrid>
                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="CommonStates">
                                <VisualState x:Name="Normal" />
                                <VisualState x:Name="Normal_AlternatingRow">
                                    <Storyboard>
                                        <ColorAnimationUsingKeyFrames Storyboard.TargetName="DGR_Border" 
                                            Storyboard.TargetProperty="(Panel.Background).(GradientBrush.GradientStops)[0].(GradientStop.Color)">
                                            <EasingColorKeyFrame KeyTime="0" Value="#AAF0C570" />
                                        </ColorAnimationUsingKeyFrames>
                                        <ColorAnimationUsingKeyFrames Storyboard.TargetName="DGR_Border" 
                                            Storyboard.TargetProperty="(Panel.Background).(GradientBrush.GradientStops)[1].(GradientStop.Color)">
                                            <EasingColorKeyFrame KeyTime="0" Value="#AAFF7F00" />
                                        </ColorAnimationUsingKeyFrames>
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="Normal_Selected">
                                    <Storyboard>
                                        <!-- ColorAnimation here same as Normal_AlternatingRow state -->
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="MouseOver">
                                    <Storyboard>
                                        <!-- ColorAnimation here same as Normal_AlternatingRow state -->
                                    </Storyboard>
                                </VisualState>
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>
                    </Border>                        
                </ControlTemplate>
            </Setter.Value>
          <Style.Triggers>
              <DataTrigger Binding="{Binding Active}" Value="Hold">
                 <Setter Property="Background" Value="Red" />
             </DataTrigger>
        </Style.Triggers>
        </Setter>                
    </Style>

As always any help would be great. Thanks M

like image 208
mHelpMe Avatar asked Sep 02 '13 20:09

mHelpMe


1 Answers

Do you need to change the behaviour of the DataGridRow, or is it sufficient to alter the style?

If changing the row highlighting based on a property is all you need, you should be able to just use a simpler Style, something like this:

    <!-- A brush -->
    <LinearGradientBrush x:Key="BgBrush1" StartPoint="0,0" EndPoint="0,1">
        <GradientStop Offset="0" Color="#888888"/>
        <GradientStop Offset="1" Color="#FFFFF86E"/>
    </LinearGradientBrush>

    <!-- Your row style -->
    <Style x:Key="HighlightRow" TargetType="{x:Type DataGridRow}">
        <Style.Triggers>
            <DataTrigger Binding="{Binding StatusGood}" Value="Hold">
                <Setter Property="Background" Value="{StaticResource BgBrush1}" />
            </DataTrigger>
        </Style.Triggers>
    </Style>

You should be able to apply the style when required in a DataGrid by using your style as a StaticResource for the RowStyle property:

<DataGrid DataContext="{Binding OrderBlock}"
          Name="dataGridOrdersGood" 
          ItemsSource="{Binding Orders}" 
          RowStyle="{StaticResource HighlightRow}" />

Edit:

If you want to retain the rest of your styling and use a control template, you can place your DataTrigger in your ControlTemplate.Triggers, you'll also have to supply a TargetName property, to specify the element you wish the trigger to act on, so using my above brush, and your initial code:

<!-- Data grid formatting Grid Row template -->
<Style x:Key="DG_Row" TargetType="{x:Type DataGridRow}">        
    <Setter Property="Template">            
        <Setter.Value>
        <!-- Your code -->
            <ControlTemplate TargetType="{x:Type DataGridRow}">
                <Border x:Name="DGR_Border"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}"
                        SnapsToDevicePixels="True">
                <!-- Your code -->
                </Border>
                <ControlTemplate.Triggers>
                    <DataTrigger Binding="{Binding StatusGood}" Value="Send">
                        <Setter TargetName="DGR_Border" Property="Background" Value="{StaticResource BgBrush1}"/>
                     </DataTrigger>
                 </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Where DGR_Border is the name you had given your border with the existing gradient.

like image 55
Chris Avatar answered Sep 21 '22 23:09

Chris