filip
filip

Reputation: 1503

Custom column template for DataGrid

I have a DataGrid bound to a DataTable.DefaultView, which renders the grid using auto generation of columns. That part works fine. However, for some columns I would like to use a custom template. The problem is that columns in the table change on each load, so the solution needs to be generic.

I can hook into the AutoGeneratingColumn event as described here, but still have problem with defining the template binding:

<UserControl.Resources>
    <DataTemplate x:Key="customCellTemplate">
        <TextBlock Text="{Binding ???"></TextBlock>
    </DataTemplate>
</UserControl.Resources>

(...)

<DataGrid ItemsSource="{Binding DefaultView}" AutoGeneratingColumn="DataGrid_AutoGeneratingColumn">
</DataGrid>

And my code behind:

private void DataGrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
    string colName = e.PropertyName;
    if (someCondition)
    {
        var templateColumn = new DataGridTemplateColumn();
        templateColumn.Header = colName;
        templateColumn.CellTemplate = (DataTemplate)Resources["customCellTemplate"];
        templateColumn.SortMemberPath = colName;
        e.Column = templateColumn;
     }

As you can see I don't know how to define the binding in the column template, because the column name changes.

EDIT:

In addition to the accepted answer - sometimes it's easier to create the entire template programmatically as described here: http://fczaja.blogspot.com/2013/12/wpf-datagrid-custom-template-for.html

Upvotes: 2

Views: 4467

Answers (1)

McGarnagle
McGarnagle

Reputation: 102753

Using a StaticResource forces you to keep it the same -- remember, static means there's just one instance, so if you change its binding for one column, you will change it for all of them. So it will have to be like this:

<DataTemplate x:Key="customCellTemplate">
    <TextBlock Text="{Binding}"></TextBlock>
</DataTemplate>

I was thinking you could use this template in a dynamic way by wrapping it in another DataTemplate using a ContentControl. Set the Content property dynamically, and use the static template for the ContentTemplate:

private void DataGrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
    string colName = e.PropertyName;
    if (someCondition)
    {
        string xaml = @"<DataTemplate xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""><ContentControl Content=""{0}"" ContentTemplate=""{1}"" /></DataTemplate>";
        var tmpl = (DataTemplate)XamlReader.Load(string.Format(xaml, "{Binding " + colName + "}", "{StaticResource customCellTemplate}"));
        var templateColumn = new DataGridTemplateColumn();
        templateColumn.CellTemplate = tmpl;
        templateColumn.Header = colName;
        templateColumn.SortMemberPath = colName;
        e.Column = templateColumn;
     }
}

The only catch is that, with this setup, I believe "customCellTemplate" will have to be defined at the application level.

Upvotes: 1

Related Questions