Styling "Empty Column" in DataGrid

Oct 11, 2009 at 11:10 AM

Lets say I have a datagrid with AlternatingRowBackground set to "Blue" so that my rows will alternate between white and blue.
I then style the DataGridColumnHeader with a Background, BorderBrush etc.
I then add three columns and populate it with some data.
If these three columns doesn't consume all the available space it will look as if there is a 4th column in the grid. The three columns I've just added and an extra "empty column". This "empty column" will have the default style set for the ColumnHeader (which is good) but its cells will have alternating background between white and blue. Is there any way to style these "extra cells" because this does not look that good.

I know I can set the width of the last column to "*" to make it stretch but this only works when there is no need for a scrollbar. In my application the visible columns are constantly changing and can be anywhere from 2 up to over 100 and if I use "*" the grid will try to fit all the columns in the visible space.

The result may look like this
___________________________________________________________________________
| Column1..........| Column2..........| Column3..........| "Empty Column"  |
| User Style...... | User Style...... | User Style....... | Default Style..........|
|-----------------|-----------------|-----------------|---------------------|
| Some value 1 | Some value 2 | Some value 3| No data..................|
| Bg=White........| Bg=White........| Bg=White........| Bg=White...............|
|-----------------|-----------------|-----------------|---------------------|
| Some value 4 | Some value 5 | Some value 6| No data..................|
| Bg=Blue...........| Bg=Blue...........| Bg=Blue...........| Bg=Blue..................|
|_________________|_________________|_________________|_____________________|

The optimal result would look like this
___________________________________________________________________________
| Column1..........| Column2..........| Column3..........| "Empty Column"  |
| User Style...... | User Style...... | User Style....... |                          |
|-----------------|-----------------|-----------------|                          |
| Some value 1 | Some value 2 | Some value 3|                          |
| Bg=White........| Bg=White........| Bg=White........| Bg=Gray            |
|-----------------|-----------------|-----------------|                          |
| Some value 4 | Some value 5 | Some value 6|                          |
| Bg=Blue...........| Bg=Blue...........| Bg=Blue...........|                          |
|_________________|_________________|_________________|_____________________|

Fredrik

Oct 12, 2009 at 12:17 PM

I figured I'd answer my own question in case anyone's reading this.
I managed to get the desired output by making a few workarounds.

First I created a Brush for the desired background
<SolidColorBrush x:Key="EmptyColumnBrush" Color="Gray"/>

Then I used this Brush for the background properties in the datagrid
<Setter Property="Background" Value="{StaticResource EmptyColumnBrush}"/>
<Setter Property="RowBackground" Value="{StaticResource EmptyColumnBrush}"/>
<Setter Property="AlternatingRowBackground" Value="{StaticResource EmptyColumnBrush}" />

After that I needed to make the DataGridCells have the alternating background, rather than the DataGridRow. I also wanted the selected cells to have Blue background and White foreground so in the DataGridCell template  I added the following
<Style.Triggers>
 
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType={x:Type wpftoolkit:DataGridRow}}, Path=AlternationIndex}" Value="1" >
   
<Setter Property="Background" Value="{StaticResource AlternateRowBackgroundBrush}"/>
  </DataTrigger>
 
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType={x:Type wpftoolkit:DataGridRow}}, Path=AlternationIndex}" Value="0" >
   
<Setter Property="Background" Value="White"/>
 
</DataTrigger>
  <Trigger Property="IsSelected" Value="True">
   
<Setter Property="Foreground" Value="White"/>
   
<Setter Property="Background" Value="#316AC5"/>
   
<Setter Property="Border.BorderBrush" Value="#316AC5"/>
 
</Trigger>
<Style.Triggers>

A few problems was still present after this
* The Grid lines was still visible in the "Empty Column"
* The background for the datagrid was still visible at the edges of cells

First I disabled the Grid lines in the datagrid
<Setter Property="GridLinesVisibility" Value="None"/>

After that these two problems required some editing in the DataGridCell.cs OnRender method.
protected override void OnRender(DrawingContext drawingContext)
{
 
base.OnRender(drawingContext);
 
  // Draw a rectangle as a secondary background for the cell to avoid visible datagrid background at the edges

 
Rect rect = new Rect(new Size(RenderSize.Width, RenderSize.Height));
  drawingContext.DrawRectangle(
Brushes.White, null, rect);

 
//if (DataGridHelper.IsGridLineVisible(DataGridOwner, /*isHorizontal = */ false))
 
{
   
// Vertical grid lines for Cell
   
double thickness = DataGridOwner.VerticalGridLineThickness;
    rect = new Rect(new Size(thickness, RenderSize.Height));
    rect.X = RenderSize.Width - thickness;
   
    // Horizontal grid lines for Cell
    thickness = DataGridOwner.HorizontalGridLineThickness;

    rect = new Rect(new Size(RenderSize.Width, thickness));
   
rect.Y = RenderSize.Height - thickness;
    drawingContext.DrawRectangle(DataGridOwner.VerticalGridLinesBrush, null, rect);
  }
}

These workarounds gave the behavior and output that I was looking for and the result looks really good.
Unfortunately I can't find a way to show pictures on this discussion board so I can't show the results but if anyone's interested in seeing it, just send me an email.
/Fredrik