在 WPF 编程中,我们通常都是在前台 XAML 中通过标记语言来编写 DataTemplate 的。曾今有小伙伴在 Stack Overflow 上提问,如何在后台通过 C# 代码来创建 DataTemplate ?我搜索了一番,找到了 FrameworkElementFactory 类,它便是生成 DataTemplate 的核心功臣。
先看一下 XAML 中实现的效果:
<Grid x:Name="RootGrid"> <DataGrid x:Name="MyDataGrid" AutoGenerateColumns="False"> <DataGrid.Columns> <DataGridTemplateColumn> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <StackPanel Orientation="Horizontal"> <TextBlock Foreground="Red" Text="{Binding ValueA}"/> <TextBlock Foreground="Blue" Text="{Binding ValueB}" /> </StackPanel> </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn> </DataGrid.Columns> </DataGrid> </Grid>将 XAML 中的效果用 C# 来实现:
public MainWindow() { InitializeComponent(); InitializeDataGrid(); } private void InitializeDataGrid() { // StackPanel and Children var stackPanelFactory = new FrameworkElementFactory(typeof(StackPanel)); stackPanelFactory.SetValue(StackPanel.OrientationProperty, Orientation.Horizontal); var textBlockFactoryA = new FrameworkElementFactory(typeof(TextBlock)); textBlockFactoryA.SetValue(TextElement.ForegroundProperty, Brushes.Red); textBlockFactoryA.SetBinding(TextBlock.TextProperty, new Binding("ValueA")); var textBlockFactoryB = new FrameworkElementFactory(typeof(TextBlock)); textBlockFactoryB.SetValue(TextElement.ForegroundProperty, Brushes.Blue); textBlockFactoryB.SetBinding(TextBlock.TextProperty, new Binding("ValueB")); stackPanelFactory.AppendChild(textBlockFactoryA); stackPanelFactory.AppendChild(textBlockFactoryB); // DataTemplate var dataTemplate = new DataTemplate { VisualTree = stackPanelFactory }; // DataGridTemplateColumn var templateColumn = new DataGridTemplateColumn { CellTemplate = dataTemplate }; _dataGrid.Columns.Add(templateColumn); // DataGrid _dataGrid.Name = "MyDataGrid"; _dataGrid.AutoGenerateColumns = false; // Add the DataGrid into RootGrid RootGrid.Children.Add(_dataGrid); } private readonly DataGrid _dataGrid = new DataGrid();