When creating a WPF DataGrid
, I have the option to set a DataTemplate
to each column's HeaderTemplate
, like this:
<DataGridTextColumn Binding="{Binding Name}">
<DataGridTextColumn.HeaderTemplate>
<DataTemplate>
<!-- just some random content, not important, but notice the bindings use RelativeSource-->
<StackPanel Orientation="Horizontal">
<TextBlock Text="Name" VerticalAlignment="Center"/>
<Button Command="{Binding Path=DataContext.SortFoldersByNameCommand, RelativeSource={RelativeSource AncestorType=DataGrid}}" Content="▲"
Foreground="{Binding Path=DataContext.IsFoldersSortByName, Converter={StaticResource EnabledToBrushConverter}, RelativeSource={RelativeSource AncestorType=DataGrid}}"/>
</StackPanel>
</DataTemplate>
</DataGridTextColumn.HeaderTemplate>
</DataGridTextColumn>
Now, notice that for my bindings to work inside that template, I need to set a RelativeSource
, because this template is not bound to the grid's DataContext
anymore.
The question is: what is bound to the header's DataTemplate
?
If I simply try to put a <TextBlock Text="{Binding}"/>
, for instance, the text is empty. I don't know what other kinds of tests I could do to find out.
The short answer is that the datacontext is nothing.
I threw a quick template into some datagrid I have on disk.
I used this thing to answer a few questions years back.
The header isn't in the visual tree and does not inherit datacontext.
My quick and dirty header template:
<DataGridTextColumn Binding="{Binding LastName}">
<DataGridTextColumn.HeaderTemplate>
<DataTemplate>
<TextBlock Text="XXXX"/>
</DataTemplate>
</DataGridTextColumn.HeaderTemplate>
</DataGridTextColumn>
Examine that textblock using Snoop...
Datacontext is empty:
This is why you do all that relativesource stuff to get to your property in the datacontext.
As an aside.
If you're doing much wpf development I recommend you give Snoop a go.
It's still way better than the in built thing.