I'm trying to customise the header content of a UWP DataGrid. I can add the necessary controls by changing the header style like this, however I want to be able to bind the controls inside the template to instances of a class that are only available when the grid columns are (dynamically) created.
How do I make the binding in the code below valid (or another workaround)?
DataGrid example XAML:
<controls:DataGrid
x:Name="DataGrid"
ItemsSource="{x:Bind ItemsSource}"
AutoGenerateColumns="False"
ColumnHeaderHeight="80">
<controls:DataGrid.ColumnHeaderStyle>
<Style TargetType="controlsprimitives:DataGridColumnHeader">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="controlsprimitives:DataGridColumnHeader">
<StackPanel Orientation="Vertical">
<TextBox Text="{x:bind PropertyOnMyClass, Mode=TwoWay}"/>
<!-- Some other controls -->
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</controls:DataGrid.ColumnHeaderStyle>
</controls:DataGrid>
Example of a column being added:
private void MakeColumn(MyClass classInstance)
{
DataGridTextColumn column = new();
column.Header = classInstance;
DataGrid.Columns.Add(column);
}
I can add controls in the way above with no issue, and I can set the DataGridTextColumn Header property to the class instance and set the header text using a GetString()
override on the class, but I can't find a way to bind to multiple properties.
A solution that creates the header controls in codebehind would also be fine, however you can't create Templates in codebehind.
Thanks in advance.
So my workaround was to call a method the first time the control loads to set the necessary links between the controls and the class:
XAML:
<controls:DataGrid.ColumnHeaderStyle>
<Style
TargetType="controlsprimitives:DataGridColumnHeader">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="controlsprimitives:DataGridColumnHeader">
<ContentPresenter Loaded="HeaderLoaded"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</controls:DataGrid.ColumnHeaderStyle>
and code behind:
private void HeaderLoaded(object sender, RoutedEventArgs e)
{
var presenter = sender as ContentPresenter;
if (presenter.DataContext is MyClassType myClassInstance)
{
presenter.Content = new ColumnHeader(myClassInstance, this);
}
presenter.Loaded -= HeaderLoaded;
}