WPF数据网格中,是否有方法为具有字符串数组的对象创建新行

d5vmydt9  于 2023-02-05  发布在  其他
关注(0)|答案(1)|浏览(148)

我正在处理一个数据网格,我放入的对象有多个属性,包括一个字符串数组。
当绑定到网格,你只能得到一行,而我需要能够有一行每一个项目在数组中的任何帮助?
我使用Command="{Binding PropX}”运行数据网格,但它只提供单行

<DataGridTextColumn Header="Names"
                            Binding="{Binding Names}"
                            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" />
    <DataGridTextColumn Header="Wants Data File"
                            Binding="{Binding WantsDataFile}"
                            Width="Auto" />

示例中的名称是一个名称数组,因此对于每个名称,我需要一个新行,其余数据保持不变。
Datagrid绑定到对象的可观察集合

public class Customer : ObservableObject{
    public   ObservableCollection<string> names {get;set;}
    public int ID {get;set;}
    public.......
}

网格与可观察到的客户集合绑定

3htmauhk

3htmauhk1#

两个选择。

1.构造按名称列出的客户视图模型的平面列表

如果您希望每个名称(而不仅仅是每个Customer)对应一行,则需要进行一对多转换,因为您最终需要一个平面数组来提供给ItemsSource。有很多方法可以实现这一点,但这里有一种:

public class CustomerByNameViewModel : ObservableObject
{
    public CustomerByNameViewModel (Customer customer, int nameIndex)
    {
        _nameIndex = nameIndex;
        this.Customer = customer;
    }           

    // what you bind to
    public int ID => Customer.ID;
    public string Name => Customer.names[_nameIndex]; 

    // not what you bind to; instead add public 
    // accessors for any other Customer properties 
    // you need
    internal Customer Customer {get; set;} 
    private int _nameIndex;
}

在主视图模型中:

CustomerByNameViewModel[] _FlatCustomerList; 
public CustomerByNameViewModel[] FlatCustomerList
{
    get
    {
        if (_FlatCustomerList == null) 
        {
            _FlatCustomerList = Customers.SelectMany(c => 
            {
               int i = 0;
               return c.Select(c2 => new CustomerByNameViewModel(c2, i++));
            }).ToArray(); // don't omit this!
        }
        return _FlatCustomerList;
    }
 }

然后将ItemsSource设置为FlatCustomerList
这样做的一个大缺点--你失去了ObservableCollection的好处。如果Customers的集合或者它们的单个名称发生了变化,你需要null输出_FlatCustomerList,并触发一个属性更改通知来重建平面列表。这不是最有效的事情,但它确实完成了这项工作。
编辑--我修改了这个选项,将Customer Package 在它自己的视图模型中,这将是一个更好的实践,以便将数据关注点与其可视化分离,并避免仅仅为了生成平面列表而创建新的Customer对象。
如果您有雄心,可以进一步扩展它,让VM侦听Customer对象上的更改并进行适当的更新。

2.使用数据网格详细信息

另一个选择是使用DataGrid细节。在我的经验中,这很少使用,但它是一个非常强大的特性。一个很好的例子是here。想法是保持当前集合不变(尽管我仍然会添加一个新的派生属性,至少总是给出列表中的第一个名称以用于主行),并使用它来填充主行。
然后在RowDetailsTemplate中你可以放任何你想放的东西;您将Customer作为DataContext,这样您就可以将Names绑定到另一个ItemsControl(如ListBox)以显示所有名称。您可能会发现这是一个比每个客户名称单独一行更好的设计选择。

相关问题