WPF:如何将含自定义类的DataTable绑定到DataGrid并自定义列
解决方案:自定义DataTable绑定DataGrid并实现单元格模板
问题背景
需要将包含自定义类std和statObj的DataTable绑定到WPF DataGrid,实现以下要求:
- 第一列(
std类型)同时显示图片和名称 - 其余列(
statObj类型)仅展示Version属性 - 所有列通过后台代码手动创建
步骤1:修改后台代码,手动创建列与模板
首先关闭DataGrid的自动列生成,然后分别为不同类型的列创建对应模板与绑定逻辑。
更新后的后台代码:
public partial class MainWindow : Window, INotifyPropertyChanged { #region Property Changed stuff public event PropertyChangedEventHandler? PropertyChanged; private void OnPropertyChanged(string property) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property)); } #endregion private DataTable _dt; public DataTable dt { get { return _dt; } set { _dt = value; OnPropertyChanged(nameof(dt)); } } public MainWindow() { InitializeComponent(); this.DataContext = this; // 创建DataTable DataTable dt = new DataTable(); dt.Columns.Add(new DataColumn("Standard", typeof(std))); dt.Columns.Add(new DataColumn("Stat1", typeof(statObj))); dt.Columns.Add(new DataColumn("Stat2", typeof(statObj))); dt.Columns.Add(new DataColumn("Stat3", typeof(statObj))); // 添加示例数据 std _std = new std { Name = "Objeto1", Id = "1", Picture = "C:\\temp\\Raccoon\\Std\\Objects\\Atmo1ManageDialogAddon\\V1.0\\Common\\Picture.png", Version = "1.0.3.2" }; statObj _stat1 = new statObj { Name = "Objeto1", Id = "1", Version = "1.0.3.2" }; statObj _stat2 = new statObj { Name = "Objeto1", Id = "1", Version = "1.0.2.2" }; statObj _stat3 = new statObj { Name = "Objeto1", Id = "1", Version = "1.0.1.2" }; for (int i = 0; i < 3; i++) { DataRow row = dt.NewRow(); row[0] = _std; row[1] = _stat1; row[2] = _stat2; row[3] = _stat3; dt.Rows.Add(row); } // 关闭自动列生成,手动创建列 dtGrid.AutoGenerateColumns = false; // 第一列:std类型自定义模板 CreateStdColumn(dtGrid); // 其余statObj类型列 CreateStatColumn(dtGrid, "Stat1"); CreateStatColumn(dtGrid, "Stat2"); CreateStatColumn(dtGrid, "Stat3"); // 设置数据源 dtGrid.ItemsSource = dt.DefaultView; this.dt = dt; } // 创建std类型列的方法 private void CreateStdColumn(DataGrid grid) { DataGridTemplateColumn stdColumn = new DataGridTemplateColumn(); stdColumn.Header = "Standard"; stdColumn.Width = new DataGridLength(200); // 构建单元格模板的控件树 FrameworkElementFactory stackPanelFactory = new FrameworkElementFactory(typeof(StackPanel)); stackPanelFactory.SetValue(StackPanel.OrientationProperty, Orientation.Horizontal); // 添加Image控件,绑定图片路径 FrameworkElementFactory imageFactory = new FrameworkElementFactory(typeof(Image)); imageFactory.SetBinding(Image.SourceProperty, new Binding("Standard.Picture")); imageFactory.SetValue(Image.WidthProperty, 30.0); imageFactory.SetValue(Image.HeightProperty, 30.0); stackPanelFactory.AppendChild(imageFactory); // 添加TextBlock控件,绑定名称 FrameworkElementFactory textBlockFactory = new FrameworkElementFactory(typeof(TextBlock)); textBlockFactory.SetBinding(TextBlock.TextProperty, new Binding("Standard.Name")); textBlockFactory.SetValue(TextBlock.MarginProperty, new Thickness(5, 0, 0, 0)); textBlockFactory.SetValue(TextBlock.VerticalAlignmentProperty, VerticalAlignment.Center); stackPanelFactory.AppendChild(textBlockFactory); DataTemplate cellTemplate = new DataTemplate(); cellTemplate.VisualTree = stackPanelFactory; stdColumn.CellTemplate = cellTemplate; grid.Columns.Add(stdColumn); } // 创建statObj类型列的方法 private void CreateStatColumn(DataGrid grid, string columnName) { DataGridTextColumn statColumn = new DataGridTextColumn(); statColumn.Header = columnName; // 绑定对应列的Version属性 statColumn.Binding = new Binding($"{columnName}.Version"); statColumn.Width = new DataGridLength(120); grid.Columns.Add(statColumn); } public class std { public string? Name { get; set; } public string? Picture { get; set; } public string? Version { get; set; } public string? Id { get; set; } } public class statObj { public string? Name { get; set; } public string? Version { get; set; } public string? Id { get; set; } } }
步骤2:简化XAML代码
无需额外绑定设置,仅保留基础DataGrid定义即可:
<Window x:Class="Raccoon.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:Raccoon" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800"> <Grid> <DataGrid x:Name="dtGrid" IsReadOnly="True"/> </Grid> </Window>
关键说明
- 关闭自动列生成:必须设置
AutoGenerateColumns=false,否则WPF会自动生成默认列,覆盖手动创建的自定义列 - 绑定路径规则:DataTable每行是
DataRowView类型,绑定需使用列名.属性名的格式(如Standard.Name) - 图片路径处理:若本地图片加载异常,可添加绑定转换器将字符串路径转换为
BitmapImage对象
内容的提问来源于stack exchange,提问作者Xelato
相关产品推荐
相关产品推荐

