【发布时间】:2018-11-14 15:34:23
【问题描述】:
我创建了一个源自DataGrid 的矩阵控件,它应该能够在单元格中显示复杂类型。然后,这些复杂类型应通过模板设置样式。
使用AutoGenerateColumns 时,DataGrid 将根据分配给ItemsSource 的列表类型自动创建列和单元格类型。
我想替换网格的行、列和单元格类型以执行自定义操作和绑定到它的视图模型。我已经能够创建自定义行和列。有什么方法可以从DataGridCell 派生并让数据网格使用该类型而不是默认类型?
我查看了 .net 源代码,发现该行使用 DataGridCellsPresenter 创建单元格,但该属性不可访问。
public class MatrixControl : DataGrid
{
public static readonly DependencyProperty COLUMN_HEADER_TEMPLATE_PROPERTY = DependencyProperty.Register(nameof(ColumnHeaderTemplate), typeof(DataTemplate), typeof(MatrixControl), new PropertyMetadata(default(object)));
public DataTemplate ColumnHeaderTemplate { get { return (DataTemplate)GetValue(COLUMN_HEADER_TEMPLATE_PROPERTY); } set { SetValue(COLUMN_HEADER_TEMPLATE_PROPERTY, value); } }
private MatrixViewModel ViewModel { get { return DataContext as MatrixViewModel; } }
public MatrixControl()
{
DataContextChanged += OnDataContextChanged;
SelectionMode = DataGridSelectionMode.Extended;
SelectionUnit = DataGridSelectionUnit.CellOrRowHeader;
AutoGenerateColumns = true;
}
private void OnDataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
{
ItemsSource = ViewModel.Rows.Select(c => new Row(c, ViewModel));
}
protected override void OnAutoGeneratingColumn(DataGridAutoGeneratingColumnEventArgs e)
{
e.Cancel = true;
Columns.Clear();
foreach (var column in ViewModel.Columns)
{
Columns.Add(new MatrixColumn(column)
{
HeaderTemplate = ColumnHeaderTemplate
});
}
}
}
class MatrixColumn : DataGridTemplateColumn
{
public object Value { get; }
public MatrixColumn(object value)
{
Value = value;
}
}
class Row
{
public object Value { get; }
public Row(object value)
{
Value = value;
}
}
class MatrixViewModel
{
public IEnumerable<object> Columns { get; set; }
public IEnumerable<object> Rows { get; set; }
}
更新:尝试替换DataGridCellsPresenter
// in data grid class
protected override DependencyObject GetContainerForItemOverride()
{
return new MatrixRow();
}
class MatrixRow : DataGridRow
{
public MatrixRow()
{
var cellPresenterProperty = GetType().GetProperty("CellsPresenter", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetProperty);
cellPresenterProperty.SetValue(this, new MatrixCellPresenter());
}
}
class MatrixCellPresenter : DataGridCellsPresenter
{
protected override DependencyObject GetContainerForItemOverride()
{
// won't get called, the presenter is overriden by the internal one
return new MatrixCell();
}
}
【问题讨论】:
-
DataGridRow的默认模板使用DataGridDetailsPresenter创建单元格。您可以覆盖DataGrid的GetContainerForItemOverride()方法以返回自定义行容器,然后实现您自己的自定义DataGridDetailsPresenter。不过,这将需要相当多的努力。 -
我试过已经从
DataGridRow派生但又一次,我不能覆盖DataGridDetailsPresenter,它隐藏在内部字段中。看来内部DataGridDetailsPresenter实例会自动将自身应用到所有行,所以通过反射在行上设置它是没有意义的 -
您仍然可以创建自定义
DataGridDetailsPresenter。或自定义DataGridRow。 -
我当然可以创建一个,但我如何告诉数据网格使用它?
-
我更新了问题。查看
DataGrid源代码时,我无法弄清楚DataGridCellsPresenter是如何以及在何处被实例化的......