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
событие.
Если вам нужно больше контроля, вы можете посмотреть на 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, но времени не было.