0
votes

I am attempting to create a WPF DataGrid that has alternating background colors. I am currently using DataGridTemplateColumn columns and setting the CellStyle background color but am not fully satisfied with this result:

Simplified Example WPF DataGrid with Alternating Column Colors

<DataGridTemplateColumn.CellStyle>
    <Style TargetType="DataGridCell">
        <Style.Triggers>
            <Trigger Property="IsSelected" Value="False">
                <Setter Property="Background" Value="#FFF7F7F7" />
            </Trigger>
        </Style.Triggers>
    </Style>
</DataGridTemplateColumn.CellStyle>

I am modeling my DataGrid off of an existing WinForms project and am attempting to duplicate its look. I am facing two problems:

  1. The different column backgrounds are attached to the cells and are not properties of grid itself. Thus unused rows do not show these backgrounds. I would like even an empty grid to show the columns and backgrounds.

  2. The column background should extend under the transparent Expander header. I believe that if (1) is satisfied, this would work as well.

Can these goals be achieved with the DataGrid directly? If not, what workarounds might solve the problem; perhaps somehow drawing the column backgrounds directly on the DataGrids panel (DataGridRowsPresenter) and supporting column resize?

Any ideas? Thanks!

NOTE: This question is similar and unanswered: WPF Datagrid Template column edit event and alternating column color


Update:

This update is based on the proposed answer by @LeslieDavies which gets me most of the way there. I have two issues with this solution:

  1. I'm not able to star size the DataGrid columns. If I attempt to star size, the columns grow continuously without bound.

  2. If I remove the DataGrid.GroupStyle from the XAML, the resizing no longer works correctly. The Rectangles grow correctly, but when shrinking the column the Rectangle shrinks but the Grid columns do not shrink properly.

XAML:

<Window x:Class="GridColumnColors.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525" Background="Black">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>
        <Rectangle Name="Rect0" Grid.Column="0" HorizontalAlignment="Left" Margin="-1,0,0,0" Fill="#FFCACACA" />
        <Rectangle Name="Rect1" Grid.Column="1" HorizontalAlignment="Left" Margin="-1,0,0,0" Fill="White"/>
        <Rectangle Name="Rect2" Grid.Column="2" HorizontalAlignment="Left" Margin="-1,0,0,0" Fill="#FFCACACA"/>
        <DataGrid Name="DataGridStudents"  AutoGenerateColumns="False" Visibility="Visible" Grid.ColumnSpan="4" ItemsSource="{Binding StudentsCollectionView}"
                    SelectionMode="Extended" GridLinesVisibility="None" RowHeaderWidth="0"  RowBackground="Transparent"
                    CanUserResizeRows="False" IsReadOnly="True" Background="Transparent" LayoutUpdated="Students_LayoutUpdated">
            <DataGrid.GroupStyle>
                <GroupStyle>
                    <GroupStyle.ContainerStyle>
                        <Style TargetType="{x:Type GroupItem}">
                            <Setter Property="Template">
                                <Setter.Value>
                                    <ControlTemplate TargetType="{x:Type GroupItem}">
                                        <Expander Header="{Binding}">
                                            <ItemsPresenter />
                                        </Expander>
                                    </ControlTemplate>
                                </Setter.Value>
                            </Setter>
                        </Style>
                    </GroupStyle.ContainerStyle>
                </GroupStyle>
            </DataGrid.GroupStyle>
            <DataGrid.Columns>
                <DataGridTextColumn Header="First Name" MinWidth="100" Binding="{Binding FirstName}"/>
                <DataGridTextColumn Header="Last Name"  MinWidth="100" Binding="{Binding LastName}"/>
                <DataGridTextColumn Header="Age"        MinWidth="100" Binding="{Binding Age}"/>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>

Code Behind:

private void Students_LayoutUpdated(object sender, EventArgs e)
{
    Rect0.Width = DataGridStudents.Columns[0].ActualWidth+3;
    Rect1.Width = DataGridStudents.Columns[1].ActualWidth+0;
    Rect2.Width = DataGridStudents.Columns[2].ActualWidth+1;
}

DataGrid With Alternating Column Colors Updated

1

1 Answers

2
votes

This is not an elegant solution but it gives you the view you want.

  1. Make the Background of the DataGrid "Transparent".
  2. Make the RowBackground of the DataGrid "Transparent".
  3. Place the DataGrid in a Grid.
  4. Create as many ColumnDefinitions in the Grid as you have columns in your DataGrid.
  5. Create as many rectangles as you have columns. Place them in the Grid in each column. Make their HorizontalAlignment "Left". Color them with their "Fill".
  6. For the DataGrid, add a LayoutChanged event.
  7. In the code for the LayoutChanged event, update the width of the rectangles. ex:

    rectangle.Width = dataGrid.Columns[0].Width.DesiredValue;

  8. Give the 1st rectangle a Margin of (7,0,0,0) due to the DataGrid styling.