WPF使用代码创建数据模板DataTemplate
起因
我们都知道, 在XAML界面当中编写DataTemplate很简单, 但是有时候我们需要在代码当中去设置DataTemplate。
该怎么办?
比如, 实际需求是DataGrid当中需要创建100个DataTemplate列, 很明显,这些列不太方便在XAML中编写。
这个时候,我们就需要在代码当中动态生成模板列。
答案
如下面所示,我创建了一个DataGridTemplateColumn,其中包含了一个StackPanel里面放了两个Button按钮。
<DataGridTemplateColumn> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <StackPanel Orientation="Horizontal"> <Button Content="编辑"/> <Button Content="删除"/> </StackPanel> </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn>
现在就是, 我们需要把这个过程用代码去生成, 这个时候我们就可以用到FrameworkElementFactory 类。
步骤分为几步:
- 创建DataGridTemplateColumn 对象, 设置Header等内容
DataGridTemplateColumn templateColumn = new DataGridTemplateColumn(); templateColumn.Header = "标题";
- 创建 FrameworkElementFactory 对象, 设置Orientation属性水平排列
FrameworkElementFactory factory = new FrameworkElementFactory(typeof(StackPanel)); factory.SetValue(StackPanel.OrientationProperty, Orientation.Horizontal);
- 向 FrameworkElementFactory 对象追加一个factory对象
FrameworkElementFactory buttonEdit = new FrameworkElementFactory(typeof(Button)); buttonEdit.SetValue(ContentProperty, "编辑"); factory.AppendChild(buttonEdit); FrameworkElementFactory buttonDel = new FrameworkElementFactory(typeof(Button)); buttonDel.SetValue(ContentProperty, "删除"); factory.AppendChild(buttonDel);
- 创建DataTemplate对象, 设置VisualTree 值为factory
DataTemplate dataTemplate = new DataTemplate(); dataTemplate.VisualTree = factory;
- 最后把DataGridTemplateColumn 的CellTemplate 值设置为dataTemplate
templateColumn.CellTemplate = dataTemplate;
最终效果
关于整个过程梳理
有一点,我们需要清楚, 在XAML界面当中编写的任何代码, 其实本质上都是转化成C#代码, 既然如此来说, 只要XAML有的对象,我们都可以用C#代码编写, 但是为什么一般我们不这么做, 是因为XAML更加容易去表达界面上的元素, 代码的可视化以及可维护性。
再回到上面, 我们需要清楚上面的流程, 我们通过FrameworkElementFactory 创建了一个完整的视觉树的对象,里面包含了一个StackPanel容器,容器中放置了两个Button控件,最终把这个 FrameworkElementFactory 对象给了DataTemplate当中的VisualTree, 这里的意思是 我们给DataTemplate设置了可视化的视觉树结构, 最终DataTemplate决定了 DataGridTemplateColumn 的视觉呈现。
完整代码
DataGridTemplateColumn CreateDataGridTemplateColumn() { DataGridTemplateColumn templateColumn = new DataGridTemplateColumn(); templateColumn.Header = "标题"; FrameworkElementFactory factory = new FrameworkElementFactory(typeof(StackPanel)); factory.SetValue(StackPanel.OrientationProperty, Orientation.Horizontal); FrameworkElementFactory buttonEdit = new FrameworkElementFactory(typeof(Button)); buttonEdit.SetValue(ContentProperty, "编辑"); factory.AppendChild(buttonEdit); FrameworkElementFactory buttonDel = new FrameworkElementFactory(typeof(Button)); buttonDel.SetValue(ContentProperty, "删除"); factory.AppendChild(buttonDel); DataTemplate dataTemplate = new DataTemplate(); dataTemplate.VisualTree = factory; templateColumn.CellTemplate = dataTemplate; return templateColumn; }