I've customized the DataGrid
a lot, but surprisingly I'm unable to add a border around the entire header area without it breaking.
So this is what I'm trying to accomplish:
The following control is responsible for displaying the header area: DataGridColumnHeadersPresenter
.
I added a border around it, and as you can see from the screenshot above, it does work, but the problems begin only when the grid is empty! (this means that also the empty row needs to be removed, which can be done by setting CanUserAddRows="False"
).
So far, here's my style:
<Border BorderBrush="Red" BorderThickness="1" Grid.Column="1">
<DataGridColumnHeadersPresenter x:Name="PART_ColumnHeadersPresenter" Margin="0,0,0,5"
Visibility="{Binding HeadersVisibility, ConverterParameter={x:Static DataGridHeadersVisibility.Column}, Converter={x:Static DataGrid.HeadersVisibilityConverter}, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}">
</DataGridColumnHeadersPresenter>
</Border>
All I did was wrap it with a border, but now when I apply filtering so that the grid is empty, the header disappears to the right and the application slows down to a crawl.
Demonstration:
If I remove the border, everything works as expected. It seems like the DataGrid is expecting a very specific tree structure, otherwise it just explodes.
I tried changing the template of the DataGridColumnHeadersPresenter
, but also that expects a very specific structure which looks like this:
<DataGridColumnHeadersPresenter.Template>
<ControlTemplate TargetType="{x:Type DataGridColumnHeadersPresenter}">
<Grid>
<DataGridColumnHeader x:Name="PART_FillerColumnHeader"
IsHitTestVisible="False" />
<ItemsPresenter />
</Grid>
</ControlTemplate>
</DataGridColumnHeadersPresenter.Template>
If I give the DataGridColumnHeader
a BorderBrush
and BorderThickness
, it doesn't look right, and if I add my own border control anywhere, the same problem arises.
The DataGridColumnHeadersPresenter
actually has BorderBrush
and BorderThickness
properties, but they have no effect at all.
One workaround I found was to set Grid.Column
to 0
so that it goes in place of the row headers column header, then just set HeadersVisibility="Column"
on the DataGrid
so it doesn't look broken, and the problem disappears. Unfortunately I need the row headers, so this is an unacceptable solution.
Default style for DataGrid can be found here, or just right-click it in Visual Studio and go to Edit Template, then Edit a Copy, which is what I did.
There must be an easy way to accomplish this that I'm probably just not seeing right now...
Ok so I just returned to tackle this problem after @jsanalytics pointed out the existence DataGridHeaderBorder
, and by analyzing the default tree structure more deeply, with a little bit of trial and error, I managed to get the job done.
I did not want the DataGridHeaderBorder
though, which is part of the Windows themes, but replaced it with a regular border.
My implementation:
<DataGridColumnHeadersPresenter Grid.Column="1" x:Name="PART_ColumnHeadersPresenter"
Visibility="{Binding HeadersVisibility, ConverterParameter={x:Static DataGridHeadersVisibility.Column}, Converter={x:Static DataGrid.HeadersVisibilityConverter}, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}">
<DataGridColumnHeadersPresenter.Template>
<ControlTemplate TargetType="{x:Type DataGridColumnHeadersPresenter}">
<Grid HorizontalAlignment="Left">
<ItemsPresenter />
<DataGridColumnHeader x:Name="PART_FillerColumnHeader" IsHitTestVisible="False">
<DataGridColumnHeader.Template>
<ControlTemplate TargetType="{x:Type DataGridColumnHeader}">
<Grid>
<Border BorderThickness="2" BorderBrush="Red">
<ContentPresenter RecognizesAccessKey="True"
SnapsToDevicePixels="True" />
</Border>
<!--Uncomment if you need these resizing grippers-->
<!--<Thumb x:Name="PART_LeftHeaderGripper" HorizontalAlignment="Left" />
<Thumb x:Name="PART_RightHeaderGripper" HorizontalAlignment="Right" />-->
</Grid>
</ControlTemplate>
</DataGridColumnHeader.Template>
</DataGridColumnHeader>
</Grid>
</ControlTemplate>
</DataGridColumnHeadersPresenter.Template>
</DataGridColumnHeadersPresenter>
You'll probably need to tweak it for your own needs, but this fills our requirements :-)