'Coloring the first and last rows in a datagrid WPF C#

Can you guy tell me a great way of coloring the last row in a datagrid in WPF, I have to color the first and last rows, I found a way to do the first one by doing the code below, but I need a way to do the last row.

<DataTrigger
Binding="{Binding RelativeSource={RelativeSource Mode=PreviousData}}"
Value="{x:Null}">
<Setter Property="Background" Value="Green"/>
</DataTrigger>


Solution 1:[1]

This is a tough one.

  • You may use the alternation index with a multi-binding on the ItemsSource and the AlternationCount, a IMultiValueConverter, and finally fail because the alternation index may not start from 0. (also, you loose the benefit of an AlternationCount of 2).
  • You may use code behind and hack the DataGrid to display the hard coded color you want. But that is not MVVM.
  • You may put a special boolean on your view model to mark those items as special. But this feels to be the wrong place.
  • ...

My approach is to inherit the DataGrid object in a class that will keep up-to-date a ‘IsAnExtremityattached property (a pretty touchy pattern) on it's DataGridRow:

public class DataGridEx : DataGrid
{
    private static readonly DependencyPropertyKey IsAnExtremityPropertyKey =
        DependencyProperty.RegisterAttachedReadOnly(
                                            "IsAnExtremity",
                                            typeof(bool),
                                            typeof(DataGridEx),
                                            new FrameworkPropertyMetadata(defaultValue: false,
                                                                          flags: FrameworkPropertyMetadataOptions.AffectsRender));

    public static readonly DependencyProperty IsAnExtremityProperty = IsAnExtremityPropertyKey.DependencyProperty;
    
    public static bool GetIsAnExtremity(DataGridRow dataGridRow)
    {
        return (bool)dataGridRow.GetValue(IsAnExtremityProperty);
    }

    private static void SetIsAnExtremity(DataGridRow dataGridRow, bool value)
    {
        dataGridRow.SetValue(IsAnExtremityPropertyKey, value);
    }

    private IReadOnlyList<DataGridRow> _extremities = Array.Empty<DataGridRow>();

    protected override void OnLoadingRow(DataGridRowEventArgs e)
    {
        base.OnLoadingRow(e);
        UpdateExtremities();
    }

    protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e)
    {
        base.OnItemsChanged(e);
        UpdateExtremities();
    }

    private void UpdateExtremities()
    {
        // Current extremities
        var extremities = new[]
            {
                ItemContainerGenerator.ContainerFromIndex(0),
                ItemContainerGenerator.ContainerFromIndex(Items.Count - 1)
            }.OfType<DataGridRow>()
             .Distinct()
             .ToArray();

        // Remove the flag from old extremities (if any).
        foreach (var oldExtremityContainer in _extremities.Except(extremities))
        {
            SetIsAnExtremity(oldExtremityContainer, false);
        }

        // Ensure the flag for new extremities.
        foreach (var extremityContainer in extremities)
        {
            SetIsAnExtremity(extremityContainer, true);
        }

        _extremities = extremities;
    }
}

Then you can use this attached property almost like any other properties in the xaml:

<controls:DataGridEx ItemsSource="{Binding Path=Items}">
    <DataGrid.RowStyle>
        <Style TargetType="DataGridRow">
            <Setter Property="Background" Value="LightBlue" />
            <Style.Triggers>
                <Trigger Property="controls:DataGridEx.IsAnExtremity" Value="True">
                    <Setter Property="Background" Value="Blue" />
                    <Setter Property="Foreground" Value="White" />
                </Trigger>
            </Style.Triggers>
        </Style>
    </DataGrid.RowStyle>
</controls:DataGridEx>

A working implementation is available here.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1