WPF DataGrid如何为含字符串数组的对象生成对应多行数据?
WPF DataGrid 按Names元素拆分多行显示解决方案
要实现每个Customer的Names集合中每个元素对应一行、其余属性保持一致的效果,核心是将嵌套的Customer数据结构扁平化,让DataGrid绑定扁平的数据集。以下是具体实现步骤:
方案一:视图模型层扁平化数据(推荐)
1. 创建扁平数据实体
定义一个包含单个Name及Customer其他属性的扁平类:
public class CustomerFlatItem : ObservableObject { public string Name { get; set; } public int ID { get; set; } public string Code { get; set; } public string Contract { get; set; } public bool WantsDataFile { get; set; } }
2. 在ViewModel中转换数据
将原ObservableCollection<Customer>转换为扁平的ObservableCollection<CustomerFlatItem>:
private ObservableCollection<CustomerFlatItem> _flattenedCustomers; public ObservableCollection<CustomerFlatItem> FlattenedCustomers { get => _flattenedCustomers; set => SetProperty(ref _flattenedCustomers, value); } // 执行数据转换的方法 private void GenerateFlattenedCustomerList(ObservableCollection<Customer> originalCustomers) { var flattenedList = new ObservableCollection<CustomerFlatItem>(); foreach (var customer in originalCustomers) { // 处理Names为空的情况(可选,根据业务需求调整) if (customer.names == null || customer.names.Count == 0) { flattenedList.Add(new CustomerFlatItem { Name = string.Empty, ID = customer.ID, Code = customer.Code, Contract = customer.Contract, WantsDataFile = customer.WantsDataFile }); continue; } // 为每个Name生成一条记录 foreach (var name in customer.names) { flattenedList.Add(new CustomerFlatItem { Name = name, ID = customer.ID, Code = customer.Code, Contract = customer.Contract, WantsDataFile = customer.WantsDataFile }); } } FlattenedCustomers = flattenedList; }
3. 修改XAML绑定
将DataGrid的ItemsSource绑定到扁平集合,并调整Names列的绑定路径:
<DataGrid ItemsSource="{Binding FlattenedCustomers}" AutoGenerateColumns="False"> <DataGrid.Columns> <DataGridTextColumn Header="Names" Binding="{Binding Name}" Width="Auto" /> <DataGridTextColumn Header="ID" Binding="{Binding ID}" Width="Auto" /> <DataGridTextColumn Header="Code" Binding="{Binding Code}" Width="Auto" /> <DataGridTextColumn Header="Contract" Binding="{Binding Contract}" Width="Auto" /> <DataGridCheckBoxColumn Header="Wants Data File" Binding="{Binding WantsDataFile}" Width="Auto" /> </DataGrid.Columns> </DataGrid>
补充:监听数据变化(可选)
如果原Customer集合或其中的Names集合需要动态更新,需订阅CollectionChanged事件,在数据变更时重新生成扁平集合:
// 假设原Customer集合为OriginalCustomers OriginalCustomers.CollectionChanged += (s, e) => { if (e.NewItems != null) { foreach (Customer newCustomer in e.NewItems) { newCustomer.names.CollectionChanged += (s2, e2) => GenerateFlattenedCustomerList(OriginalCustomers); } } GenerateFlattenedCustomerList(OriginalCustomers); };
方案二:行细节模板(适合需保留原结构的场景)
若不需要完全扁平化,可通过行细节展开显示所有Names,但此方案不会将Name与主属性并列显示:
<DataGrid ItemsSource="{Binding Customers}" AutoGenerateColumns="False"> <DataGrid.Columns> <DataGridTextColumn Header="ID" Binding="{Binding ID}" Width="Auto" /> <DataGridTextColumn Header="Code" Binding="{Binding Code}" Width="Auto" /> <DataGridTextColumn Header="Contract" Binding="{Binding Contract}" Width="Auto" /> <DataGridCheckBoxColumn Header="Wants Data File" Binding="{Binding WantsDataFile}" Width="Auto" /> </DataGrid.Columns> <DataGrid.RowDetailsTemplate> <DataTemplate> <DataGrid ItemsSource="{Binding names}" AutoGenerateColumns="False"> <DataGrid.Columns> <DataGridTextColumn Header="Names" Binding="{Binding}" Width="Auto" /> </DataGrid.Columns> </DataGrid> </DataTemplate> </DataGrid.RowDetailsTemplate> </DataGrid>
内容的提问来源于stack exchange,提问作者Todd Owen
相关产品推荐
相关产品推荐

