ItemTemplateSelector в WPF Datagrid с AutoGenerateColumns

В нашей сетке данных мы используем ItemTemplateSelector переключаться между двумя шаблонами данных на основе данных, привязанных к конкретной ячейке.

Поскольку количество столбцов зависит от текущего набора данных, который мы используем AutoGenerateColumns в нашем DataGrid,

Похоже, что эта конкретная комбинация не работает хорошо -
селектор шаблонов даже не вызывается.

Можем ли мы использовать селектор шаблонов в сетке данных, где столбцы создаются автоматически?

Более конкретно: возможно ли это с помощью XAML только без помещения логики в файл code-behind или с использованием пользовательских поведений?

Наше определение сетки данных довольно тривиально:

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

Определение селектора шаблона элемента:

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

2 ответа

Первый,

ItemTemplate и ItemTemplateSelector являются унаследованными свойствами, которые намеренно игнорируются в DataGrid, поскольку они на самом деле не применяются к DataGrid так, как предполагалось в ItemsControl.

Во-вторых, если вы хотите изменить шаблоны ячеек в зависимости от их значения, вы ищете CellTemplateSelector, на DataGridTemplateColumn,

Однако, когда вы автоматически генерируете столбцы, он уже автоматически выбирает базовые типы.

Вы можете изменить это поведение в GeneratingColumns событие.

См. Следующее: принудительное использование DataTemplateCell с помощью CellTemplateSelector в столбцах с автоматическим созданием сетки данных WPF.

Если вам нужно больше контроля, вы можете посмотреть на https://zamjad.wordpress.com/2011/09/17/datagrid-with-dynamic-columns-revisited/

Я недавно столкнулся с этой проблемой и решил ее следующим образом:

мы можем унаследовать класс 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;
    }
}

Далее в обработчике события, где генерируется столбец, я делаю:

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;
    }
}

В ресурсах окна у меня есть соответствующие шаблоны.

Делать можно через DataTemplateSelector, но времени не было.

Другие вопросы по тегам