将datagrid列绑定到视图模型

时间:2019-04-30 20:26:41

标签: c# wpf mvvm datagrid

我的视图模型运行良好,基本上具有以下属性:

    -ItemCollection
       - Name
       - Type
       - DayCollection
           - DateOfDay
           - Value

我现在正在尝试使视图按如下所示呈现数据:

Name | Type  | DateOfDay1 | DateOfDay2 | DateOfDay3 ...
Dave | Actual| 1.2        | 1.8        | 5.4
Mary | Actual| 3.4        | 2.3        | 6.4
...

问题在于,当我将ItemCollection绑定到视图中的Datagrid时,该视图将显示:

Name | Type  | DayCollection
Dave | Actual| (Collection)
Mary | Actual| (Collection)

至关重要的是-与下面的某些示例不同,我的用例更加简单-ItemCollection中的所有项目在DayCollection中的总天数始终相同-即,表中的所有行都具有相同的天数列。虽然请注意,不同的ItemCollections可能具有不同的天数(但在该ItemCollection中,所有Item的天数都将相同)-因此,我不能只展平以上视图模型并具有ItemCollection,例如:

-ItemCollection
    - Name
    - Type
    - Day1
    - Day2
    - Day3

作为一个ItemCollection(表)可能还有5天,而另外30天。

我发现以下有关动态添加列的文章-编辑时不需要添加或删除列-列数是固定的:

https://www.codeproject.com/Articles/899637/Dynamic-Columns-in-a-WPF-DataGrid-Control-Part

http://www.unixresources.net/faq/320089.shtml

https://www.codeproject.com/Tips/676530/How-to-Add-Columns-to-a-DataGri

我发现上述示例过于复杂,因为我认为这是一个非常简单的用例-可变数量的项目(行),但是每行中列的数量固定(预定)[上面的最后文章写得很好]。我有点希望我可以使用重复的xaml来简单地定义列,例如:

<DataGrid ...>
    <DataGrid.Columns>
         <DataGridTextColumn Header="Name" Binding="{Binding Name}" />
         <DataGridTextColumn Header="Type" Binding="{Binding Type}" />    
         <Repeater ItemsSource="{Binding DayCollection}">
             <DataGridTextColumn Header="{Binding DateOfDay}" Binding="{Binding Value}" />
         </Repeater>
    </DataGrid.Columns>
</DataGrid>

类似上述的内容将是一个简单用例的简单解决方案,但显然不支持

我敢肯定,有一个简单的解决方案可以解决这个简单的问题,但是我找不到任何方法可以实现上述目的-上面引用的文章似乎过多,并且针对更复杂的用例(可变的列数和可以动态添加和删除的列)-我不需要这种灵活性,我也不想实现它只是为了获得固定数量的列。

我唯一想到的就是在视图模型中具有诸如ToDataTable()之类的属性,该属性将从我的视图模型中输出一个包含完整行和列的数据表,我可以将数据网格绑定到该表这似乎是一种浪费-然后将变得更加难以检查更新并将其引导到上述工作视图模型中已经存在的业务逻辑中。

是否有一个简单的解决方案,或者我是否会为一个简单的用例投入大量代码?

2 个答案:

答案 0 :(得分:3)

视图模型的全部要点是以视图易于使用的格式准备数据。如果您的视图模型没有做到这一点,那么它就不能“完美地工作”,实际上,它甚至还没有完成应做的一项工作!您需要做的是创建一个中间结构,以正确的格式解压缩数据,然后use data-binding to create your columns dynamically

您已经发现,使用诸如行为等之类的东西确实存在解决此问题的通用解决方案。行为通常比代码隐藏更干净,更通用,但是它们仍然是视图层的一部分,因此这些解决方案是真的只是试图将糟糕的视图模型数据插入视图的创可贴。您应该做的是解决更基本的基础问题,并在视图模型层中解决该问题。

执行此操作的方法有很多,但是一个简单的解决方案是将所有数据打包到DataTable中,然后将DataGrid绑定到该表中。这段代码应该给出一个大概的实现方法的粗略想法:

<DataGrid ItemsSource="{Binding MyTable}" />

...

public class MainViewModel : ViewModelBase
{
    public DataTable MyTable { get; } = new DataTable();
    private int NumColumns = 3;

    public MainViewModel()
    {
        this.MyTable = new DataTable();
        this.MyTable.Columns.Add("Name");
        this.MyTable.Columns.Add("Type");
        for (int i = 1; i <= NumColumns; i++)
            this.MyTable.Columns.Add($"Day {i}");

        var row = this.MyTable.NewRow();
        row.ItemArray = new object[] { "Tom", "Type A", "1.2", "2.3", "3.4" };
        this.MyTable.Rows.Add(row);

        row = this.MyTable.NewRow();
        row.ItemArray = new object[] { "Dick", "Type B", "2.3", "3.4", "4.5" };
        this.MyTable.Rows.Add(row);

        row = this.MyTable.NewRow();
        row.ItemArray = new object[] { "Harry", "Type C", "3.4", "4.5", "5.6" };
        this.MyTable.Rows.Add(row);
    }
}

enter image description here

答案 1 :(得分:0)

经过几天的寻找更好的解决方案,我终于找到了上面链接中的第三个。我仍然觉得这是一个非常复杂的解决方案,对于应该很简单的事物而言,但是它可以工作并且非常可重用。

https://www.codeproject.com/Tips/676530/How-to-Add-Columns-to-a-DataGri