如何用FrameworkElementFactory为DataGrid添加DataGridTemplateColumn并解决报错?
解决用FrameworkElementFactory添加DataGrid列的异常问题
咱们先拆解一下你遇到的异常原因:
System.ArgumentException: 类型“DataGridTemplateColumn”必须派生自“FrameworkElement”、“FrameworkContentElement”或“Visual3D”。
这个报错的核心是用错了方法:FrameworkElementFactory.AppendChild()是用来往可视化树里添加UI元素的(比如Button、TextBlock这类看得见的控件),但DataGridTextColumn(包括其他DataGrid列类型)并不是可视化元素——它是DataGrid的配置项,负责定义列的显示规则,不属于可视化树的一部分,所以根本不能用AppendChild来添加。
正确的实现方式(基于FrameworkElementFactory)
既然你要坚持用FrameworkElementFactory,那得换个思路:直接给DataGrid的Columns属性赋值,而不是往可视化树里塞列。具体代码修改如下:
var element = new FrameworkElementFactory(typeof(DataGrid)); if (reflectionInfo.Type.GenericTypeArguments.Count() == 1) { var subType = reflectionInfo.Type.GenericTypeArguments[0]; var fields = subType.GetFieldsRecursive(""); // 1. 创建列集合,用来存放所有生成的DataGrid列 var columnsCollection = new ObservableCollection<DataGridColumn>(); foreach (var field in fields) { var textColumn = new DataGridTextColumn(); var columnBinding = new Binding(field.Path) { Mode = BindingMode.TwoWay, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged }; // 2. 给DataGridTextColumn设置绑定(注意是列自身的Binding属性,不是TextBlock的属性) textColumn.Binding = columnBinding; // 可选:设置列头显示字段名 textColumn.Header = field.Name; columnsCollection.Add(textColumn); } // 3. 通过SetValue把列集合赋值给DataGrid的Columns属性 element.SetValue(DataGrid.ColumnsProperty, columnsCollection); } return element;
额外说明
- 你之前的代码里错误地给
FrameworkElementFactory(typeof(DataGridTextColumn))设置了TextBlock.TextProperty绑定,这是混淆了列的配置和单元格内容的绑定——DataGridTextColumn本身自带Binding属性,专门用来指定单元格数据的绑定关系。 - 虽然官方已经标记
FrameworkElementFactory为弃用(推荐用XAML或代码创建ControlTemplate的新API),但如果你的场景必须依赖它,上面的代码可以完美解决你的异常问题。
内容的提问来源于stack exchange,提问作者Daniel Pfeuffer
相关产品推荐
相关产品推荐

