如何将WPF DataGrid与包含DataTable的父类进行绑定?
问题解决:WPF DataGrid绑定父类中DataTable的列值
你的核心问题是绑定路径错误:ColumnOne和ColumnTwo并非ParentClass的直接属性,而是其内部Data(DataTable)的列,同时原代码还存在Data未初始化的空引用问题,以下是具体修复方案:
第一步:修正后台代码的空引用问题
在ParentClass构造函数中必须先初始化DataTable,否则会抛出NullReferenceException:
public class ParentClass { public string PropertyOne { get; set; } public string PropertyTwo { get; set; } public string PropertyThree { get; set; } public string PropertyFour { get; set; } public DataTable Data { get; set; } public ParentClass() { // 先初始化DataTable,避免空引用 Data = new DataTable(); Data.Columns.Add("ColumnOne"); Data.Columns.Add("ColumnTwo"); DataRow objRow = Data.NewRow(); objRow["ColumnOne"] = "ColumnOne"; objRow["ColumnTwo"] = "ColumnTwo"; Data.Rows.Add(objRow); } }
第二步:绑定DataTable的列值(两种可选方案)
方案1:直接在XAML中指定完整绑定路径
如果不想修改ParentClass,可以通过完整路径访问DataTable的第一行数据(你的示例中每个ParentClass的DataTable只有一行),同时添加FallbackValue避免无数据时显示绑定错误:
<DataGrid.Columns> <DataGridTextColumn Header="First" Width="150" Binding="{Binding PropertyOne}"/> <DataGridTextColumn Header="Second" Width="150" Binding="{Binding PropertyTwo}"/> <DataGridTextColumn Header="Third" Width="150" Binding="{Binding PropertyThree}"/> <DataGridTextColumn Header="Fourth" Width="150" Binding="{Binding PropertyFour}"/> <!-- 绑定DataTable第一行的ColumnOne --> <DataGridTextColumn Header="Fifth" Width="150" Binding="{Binding Data.Rows[0][ColumnOne], FallbackValue=''}"/> <!-- 绑定DataTable第一行的ColumnTwo --> <DataGridTemplateColumn Header="Sixth" Width="150"> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <TextBlock Text="{Binding Data.Rows[0][ColumnTwo], FallbackValue=''}"/> </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn> </DataGrid.Columns>
注意:如果需要双向绑定(允许编辑),需改用
Data.DefaultView[0][ColumnOne],因为DataRowView支持双向绑定,而DataRow不支持:Binding="{Binding Data.DefaultView[0][ColumnOne], FallbackValue=''}"
方案2:在ParentClass中添加只读属性(推荐)
为了让绑定更清晰、更安全(避免空索引异常),可以在ParentClass中添加只读属性,封装DataTable的列值获取逻辑:
public class ParentClass { // ... 原有属性保持不变 ... // 封装DataTable的列值,避免直接在XAML中写复杂路径 public string ColumnOne { get { if (Data?.Rows.Count <= 0) return string.Empty; return Data.Rows[0]["ColumnOne"].ToString() ?? string.Empty; } } public string ColumnTwo { get { if (Data?.Rows.Count <= 0) return string.Empty; return Data.Rows[0]["ColumnTwo"].ToString() ?? string.Empty; } } // ... 构造函数保持不变 ... }
此时XAML中的绑定可以和前四列完全一致,简洁明了:
<DataGrid.Columns> <DataGridTextColumn Header="First" Width="150" Binding="{Binding PropertyOne}"/> <DataGridTextColumn Header="Second" Width="150" Binding="{Binding PropertyTwo}"/> <DataGridTextColumn Header="Third" Width="150" Binding="{Binding PropertyThree}"/> <DataGridTextColumn Header="Fourth" Width="150" Binding="{Binding PropertyFour}"/> <DataGridTextColumn Header="Fifth" Width="150" Binding="{Binding ColumnOne}"/> <DataGridTemplateColumn Header="Sixth" Width="150"> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <TextBlock Text="{Binding ColumnTwo}"/> </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn> </DataGrid.Columns>
额外说明
如果你的DataTable可能包含多行数据,上述方案只能显示第一行。这种情况下建议重新设计数据结构:比如将DataTable替换为ObservableCollection<ChildClass>(ChildClass包含ColumnOne和ColumnTwo属性),或者在DataGrid中嵌套子DataGrid来显示多行数据。
内容的提问来源于stack exchange,提问作者Tiyyob
相关产品推荐
相关产品推荐

