如何在C# WPF中动态创建DataGridView?附自定义数据展示需求
在WPF中动态创建符合行列转换需求的DataGrid
你的核心需求是把扁平的参数列表转换成按参数名分组、后缀作为列的矩阵式展示,自动生成列无法满足这种行列转换的要求,需要通过数据结构转换+动态列生成来实现,以下是具体步骤和完整示例:
1. 先转换数据结构
原始的Parameter列表是每行存储一个「参数名+后缀+值」,我们需要把它转换成每行对应一个参数名、每列对应一个后缀的结构,这里提供两种实现方式:
方式一:强类型ViewModel(适合后缀固定的场景)
如果你的后缀列表(BA1-BA6)是固定的,可以创建对应的数据类:
public class ParameterRow { public string Name { get; set; } // 对应Parameter的Prefix public string BA1 { get; set; } public string BA2 { get; set; } public string BA3 { get; set; } public string BA4 { get; set; } public string BA5 { get; set; } public string BA6 { get; set; } }
然后编写转换方法,把Mother中的数据映射成List<ParameterRow>:
public List<ParameterRow> ConvertToParameterRows(Mother mother, List<string> prefixes, List<string> suffixes) { var rows = new List<ParameterRow>(); foreach (var prefix in prefixes) { var row = new ParameterRow { Name = prefix }; // 给每个后缀列赋值,无数据则留空 foreach (var suffix in suffixes) { var param = mother.parameters.FirstOrDefault(p => p.Prefix == prefix && p.Suffix == suffix); switch(suffix) { case "BA1": row.BA1 = param?.Value ?? string.Empty; break; case "BA2": row.BA2 = param?.Value ?? string.Empty; break; case "BA3": row.BA3 = param?.Value ?? string.Empty; break; case "BA4": row.BA4 = param?.Value ?? string.Empty; break; case "BA5": row.BA5 = param?.Value ?? string.Empty; break; case "BA6": row.BA6 = param?.Value ?? string.Empty; break; } } rows.Add(row); } return rows; }
方式二:动态类型(适合后缀动态变化的场景)
如果后缀列表可能随时修改,用ExpandoObject可以避免频繁修改ViewModel:
public List<dynamic> ConvertToDynamicRows(Mother mother, List<string> prefixes, List<string> suffixes) { var rows = new List<dynamic>(); foreach (var prefix in prefixes) { dynamic row = new ExpandoObject(); row.Name = prefix; var dict = (IDictionary<string, object>)row; // 动态添加后缀对应的属性 foreach (var suffix in suffixes) { var param = mother.parameters.FirstOrDefault(p => p.Prefix == prefix && p.Suffix == suffix); dict[suffix] = param?.Value ?? string.Empty; } rows.Add(row); } return rows; }
2. 动态生成DataGrid列
修改XAML,关闭自动生成列,给DataGrid命名以便后台操作:
<DataTemplate DataType="{x:Type local:Mother}"> <DataGrid x:Name="parameterGrid" AutoGenerateColumns="False" /> </DataTemplate>
然后在后台代码中(比如窗口Loaded事件、DataTemplate加载事件)动态创建列:
private void SetupDataGridColumns(List<string> suffixes) { // 添加第一列:参数名列 parameterGrid.Columns.Add(new DataGridTextColumn { Header = "Name", Binding = new Binding("Name"), Width = new DataGridLength(1.5, DataGridLengthUnitType.Star) // 占比更大,方便显示参数名 }); // 循环添加每个后缀对应的列 foreach (var suffix in suffixes) { parameterGrid.Columns.Add(new DataGridTextColumn { Header = suffix, Binding = new Binding(suffix), Width = new DataGridLength(1, DataGridLengthUnitType.Star) }); } }
3. 绑定数据源到DataGrid
最后把转换后的数据集绑定到DataGrid:
// 模拟初始化数据 var mother = new Mother(); mother.parameters.AddRange(new List<Parameter> { new Parameter { Prefix = "Parameter1", Suffix = "BA1", Value = "55" }, new Parameter { Prefix = "Parameter1", Suffix = "BA2", Value = "58" }, new Parameter { Prefix = "Parameter1", Suffix = "BA3", Value = "1" }, new Parameter { Prefix = "Parameter1", Suffix = "BA4", Value = "77" }, new Parameter { Prefix = "Parameter1", Suffix = "BA5", Value = "7889" }, new Parameter { Prefix = "Parameter1", Suffix = "BA6", Value = "100" }, new Parameter { Prefix = "Parameter2", Suffix = "BA1", Value = "7" }, new Parameter { Prefix = "Parameter2", Suffix = "BA2", Value = "44" } }); var prefixes = new List<string> { "Parameter1", "Parameter2", "Parameter3", "Parameter4" }; var suffixes = new List<string> { "BA1", "BA2", "BA3", "BA4", "BA5", "BA6" }; // 转换数据(二选一) var rows = ConvertToParameterRows(mother, prefixes, suffixes); // var rows = ConvertToDynamicRows(mother, prefixes, suffixes); // 设置列和数据源 SetupDataGridColumns(suffixes); parameterGrid.ItemsSource = rows;
完整可运行示例
如果是在Window中使用,完整代码如下:
MainWindow.xaml
<Window x:Class="WpfApp.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:WpfApp" Title="MainWindow" Height="450" Width="800" Loaded="Window_Loaded"> <Grid> <DataGrid x:Name="parameterGrid" AutoGenerateColumns="False" /> </Grid> </Window>
MainWindow.xaml.cs
using System.Collections.Generic; using System.Dynamic; using System.Linq; using System.Windows; using System.Windows.Controls; namespace WpfApp { public class Parameter { public string Prefix { get; set; } public string Suffix { get; set; } public string Value { get; set; } } public class Mother { public List<Parameter> parameters { get; set; } = new List<Parameter>(); } public class ParameterRow { public string Name { get; set; } public string BA1 { get; set; } public string BA2 { get; set; } public string BA3 { get; set; } public string BA4 { get; set; } public string BA5 { get; set; } public string BA6 { get; set; } } public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void Window_Loaded(object sender, RoutedEventArgs e) { // 模拟填充数据 var mother = new Mother(); mother.parameters.AddRange(new List<Parameter> { new Parameter { Prefix = "Parameter1", Suffix = "BA1", Value = "55" }, new Parameter { Prefix = "Parameter1", Suffix = "BA2", Value = "58" }, new Parameter { Prefix = "Parameter1", Suffix = "BA3", Value = "1" }, new Parameter { Prefix = "Parameter1", Suffix = "BA4", Value = "77" }, new Parameter { Prefix = "Parameter1", Suffix = "BA5", Value = "7889" }, new Parameter { Prefix = "Parameter1", Suffix = "BA6", Value = "100" }, new Parameter { Prefix = "Parameter2", Suffix = "BA1", Value = "7" }, new Parameter { Prefix = "Parameter2", Suffix = "BA2", Value = "44" } }); var prefixes = new List<string> { "Parameter1", "Parameter2", "Parameter3", "Parameter4" }; var suffixes = new List<string> { "BA1", "BA2", "BA3", "BA4", "BA5", "BA6" }; // 转换数据并绑定 var rows = ConvertToParameterRows(mother, prefixes, suffixes); SetupDataGridColumns(suffixes); parameterGrid.ItemsSource = rows; } private List<ParameterRow> ConvertToParameterRows(Mother mother, List<string> prefixes, List<string> suffixes) { var rows = new List<ParameterRow>(); foreach (var prefix in prefixes) { var row = new ParameterRow { Name = prefix }; foreach (var suffix in suffixes) { var param = mother.parameters.FirstOrDefault(p => p.Prefix == prefix && p.Suffix == suffix); switch (suffix) { case "BA1": row.BA1 = param?.Value ?? string.Empty; break; case "BA2": row.BA2 = param?.Value ?? string.Empty; break; case "BA3": row.BA3 = param?.Value ?? string.Empty; break; case "BA4": row.BA4 = param?.Value ?? string.Empty; break; case "BA5": row.BA5 = param?.Value ?? string.Empty; break; case "BA6": row.BA6 = param?.Value ?? string.Empty; break; } } rows.Add(row); } return rows; } private void SetupDataGridColumns(List<string> suffixes) { parameterGrid.Columns.Add(new DataGridTextColumn { Header = "Name", Binding = new Binding("Name"), Width = new DataGridLength(1.5, DataGridLengthUnitType.Star) }); foreach (var suffix in suffixes) { parameterGrid.Columns.Add(new DataGridTextColumn { Header = suffix, Binding = new Binding(suffix), Width = new DataGridLength(1, DataGridLengthUnitType.Star) }); } } } }
内容的提问来源于stack exchange,提问作者MadaraUtchi
相关产品推荐
相关产品推荐

