ItemTemplateSelector in WPF Datagrid with AutoGenerateColumns

4.2k Views Asked by At

In our data grid we're using an ItemTemplateSelector to switch between two data templates based on the data bound to a particular cell.

As the number of columns depends on the current data set we're using AutoGenerateColumns in our DataGrid.

It appears that this particular combination does not work well -
the template selector isn't even called.

Can we use the template selector in a data grid where columns are created automatically?

More specifically: Is this possible using XAML only w/o putting logic into the code-behind file or using custom behaviours?

Our data grid definition is fairly trivial:

 <DataGrid
     ItemTemplateSelector="{StaticResource myCustomDataTemplateSelector}"
     ItemsSource="{Binding MyData}">
     <DataGrid.Columns>
     </DataGrid.Columns>
 </DataGrid>

The item template selector definition:

<UserControl.Resources>
    <ResourceDictionary>
        <helpers:CustomDataTemplateSelector x:Key="myCustomDataTemplateSelector"/>
    </ResourceDictionary>
</UserControl.Resources>
2

There are 2 best solutions below

0
On

I recently ran into this problem and solved it this way:

we can inherit the class DataGridBoundColumn

public class DataGridProcessContainerColumn : DataGridBoundColumn
{
    public DataTemplate ContentTemplate { get; set; }

    protected override FrameworkElement GenerateEditingElement(DataGridCell cell, object dataItem)
    {
        throw new NotImplementedException();
    }

    protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem)
    {
        var control = new ContentControl();
        control.ContentTemplate = ContentTemplate;
        BindingOperations.SetBinding(control, ContentControl.ContentProperty, Binding);
        return control;
    }
}

Next, in the event handler, where the column is generated, I do:

private void DataGrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
    DataTemplate template = null;

    // Four lines below replace the DataTemplateSelector
    // You need to select the desired template according to your conditions
    if (e.PropertyType.IsAssignableFrom(typeof(IEnumerable<MyClass2>)))
        template = (DataTemplate)Resources["MyClass2CollectionTemplate"];
    else if (e.PropertyType.IsAssignableFrom(typeof(MyClass2)))
        template = (DataTemplate)Resources["MyClass2Template"];

    if (template != null)
    {
        var col = new DataGridProcessContainerColumn();
        col.Binding = (e.Column as DataGridBoundColumn).Binding;
        col.ContentTemplate = template;
        col.Header = e.Column.Header;
        e.Column = col;
    }
}

In the resources of the window I have the corresponding templates.

It is possible to do through DataTemplateSelector, but there was no time.

2
On

First,

ItemTemplate and ItemTemplateSelector are inherited properties which are purposely ignored in the DataGrid since they don't really apply to DataGrid in the way that they were meant to in ItemsControl.

Secondly, if you mean that you want to modify cell templae based on its value, you are looking for CellTemplateSelector, on a DataGridTemplateColumn.

However, when you auto-generate columns, it already chooses the underlying types automatically.

You can override that behavior in GeneratingColumns event.

See this: Force DataTemplateCell with CellTemplateSelector in WPF DataGrid Autogenerated columns

If you need more control, you might want to take a look at https://zamjad.wordpress.com/2011/09/17/datagrid-with-dynamic-columns-revisited/