'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 theAlternationCount
, aIMultiValueConverter
, and finally fail because the alternation index may not start from 0. (also, you loose the benefit of anAlternationCount
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 ‘IsAnExtremity
’ attached 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 |