C# c MVVM在选择组合框后更新数据网格

C# c MVVM在选择组合框后更新数据网格,c#,wpf,mvvm,data-binding,datagrid,C#,Wpf,Mvvm,Data Binding,Datagrid,我正在创建一个小的wpf程序,它按日期过滤数据集。它最终将对数据进行分组和求和,但目前我只是尝试显示数据行。我想要一个窗口,顶部有一个ComboBox,可以选择日期,还有一个DataGrid,显示正确的记录。我已经将ComboBox绑定到可能的日期列表,并将标签绑定到ComboBox更新的值。当我从组合框中选择值时,此标签将更新。但是,我无法更新DataGrid以显示新数据 数据集被传递给ViewModel构造函数,后者提取两个数据表。一个用于通过WorkItemsDates为要绑定到的Comb

我正在创建一个小的wpf程序,它按日期过滤数据集。它最终将对数据进行分组和求和,但目前我只是尝试显示数据行。我想要一个窗口,顶部有一个ComboBox,可以选择日期,还有一个DataGrid,显示正确的记录。我已经将ComboBox绑定到可能的日期列表,并将标签绑定到ComboBox更新的值。当我从组合框中选择值时,此标签将更新。但是,我无法更新DataGrid以显示新数据

数据集被传递给ViewModel构造函数,后者提取两个数据表。一个用于通过WorkItemsDates为要绑定到的ComboBoxs项创建ObservableCollection。另一个存储在DataGrid中,以便通过过滤和最终分组/求和等属性工作项绑定到。组合框绑定到DateTime SelectedDate。标签还绑定到SelectedDate,以确保组合框正在更新它

Xaml视图如下所示:

<Window ...>
    <DockPanel>
        <ComboBox DockPanel.Dock="Top" 
                  ItemsSource="{Binding WorkItemsDates}" 
                  SelectedItem="{Binding SelectedDate, Mode=TwoWay}"
                  ItemStringFormat="ddd d MMM yyyy" 
                  IsSynchronizedWithCurrentItem="True" />

        <Label DockPanel.Dock="Bottom" 
               Content="{Binding SelectedDate, FallbackValue=99/99/9999}" 
               ContentStringFormat="dd MM yyyy" />

        <DataGrid Name="TimeTotalsDataGrid" AutoGenerateColumns="True" 
                  ItemsSource="{Binding WorkItems, Mode=OneWay}"            
                  IsSynchronizedWithCurrentItem="True" ></DataGrid>
    </DockPanel>
</Window>
internal class TimeTotalsDateSelectorViewModel
{
    private ObservableCollection<DateTime> _workItemsDates;
    private DataTable _workItems;
    private DateTime _selectedDate;

    public TimeTotalsDateSelectorViewModel(DataSet tigerDataSet)
    {
        if (tigerDataSet == null)
            throw new ArgumentNullException("workItemsDates");
        if (tigerDataSet.Tables["WorkItemsDates"] == null)
            throw new ArgumentNullException("tigerDataSet.Tables[WorkItemsDates]");
        if (tigerDataSet.Tables["WorkItems"] == null)
            throw new ArgumentNullException("tigerDataSet.Tables[WorkItems]");

        _workItems = tigerDataSet.Tables["WorkItems"];

        _workItemsDates = new ObservableCollection<DateTime>();
        foreach (DataRow row in tigerDataSet.Tables["WorkItemsDates"].Rows)
        {
            _workItemsDates.Add((DateTime)row["FinishDate"]);
        }

        SelectedDate = _workItemsDates[0];
    }

    public ObservableCollection<DateTime> WorkItemsDates 
    {
        get { return _workItemsDates; }
    }

    public DateTime SelectedDate 
    { 
        get { return _selectedDate; }
        set { _selectedDate = value; }
    }

    public DataTable WorkItems
    {
        get
        {
            DataRow[] _workItemsToShow = _workItems.Select("FinishTime>='" + _selectedDate.ToString() + "' AND FinishTime<'" + _selectedDate.AddDays(1).ToString() + "'");
            return _workItemsToShow.Count() != 0 ? _workItemsToShow.CopyToDataTable() : null;
        }
    }
ViewModel如下所示:

<Window ...>
    <DockPanel>
        <ComboBox DockPanel.Dock="Top" 
                  ItemsSource="{Binding WorkItemsDates}" 
                  SelectedItem="{Binding SelectedDate, Mode=TwoWay}"
                  ItemStringFormat="ddd d MMM yyyy" 
                  IsSynchronizedWithCurrentItem="True" />

        <Label DockPanel.Dock="Bottom" 
               Content="{Binding SelectedDate, FallbackValue=99/99/9999}" 
               ContentStringFormat="dd MM yyyy" />

        <DataGrid Name="TimeTotalsDataGrid" AutoGenerateColumns="True" 
                  ItemsSource="{Binding WorkItems, Mode=OneWay}"            
                  IsSynchronizedWithCurrentItem="True" ></DataGrid>
    </DockPanel>
</Window>
internal class TimeTotalsDateSelectorViewModel
{
    private ObservableCollection<DateTime> _workItemsDates;
    private DataTable _workItems;
    private DateTime _selectedDate;

    public TimeTotalsDateSelectorViewModel(DataSet tigerDataSet)
    {
        if (tigerDataSet == null)
            throw new ArgumentNullException("workItemsDates");
        if (tigerDataSet.Tables["WorkItemsDates"] == null)
            throw new ArgumentNullException("tigerDataSet.Tables[WorkItemsDates]");
        if (tigerDataSet.Tables["WorkItems"] == null)
            throw new ArgumentNullException("tigerDataSet.Tables[WorkItems]");

        _workItems = tigerDataSet.Tables["WorkItems"];

        _workItemsDates = new ObservableCollection<DateTime>();
        foreach (DataRow row in tigerDataSet.Tables["WorkItemsDates"].Rows)
        {
            _workItemsDates.Add((DateTime)row["FinishDate"]);
        }

        SelectedDate = _workItemsDates[0];
    }

    public ObservableCollection<DateTime> WorkItemsDates 
    {
        get { return _workItemsDates; }
    }

    public DateTime SelectedDate 
    { 
        get { return _selectedDate; }
        set { _selectedDate = value; }
    }

    public DataTable WorkItems
    {
        get
        {
            DataRow[] _workItemsToShow = _workItems.Select("FinishTime>='" + _selectedDate.ToString() + "' AND FinishTime<'" + _selectedDate.AddDays(1).ToString() + "'");
            return _workItemsToShow.Count() != 0 ? _workItemsToShow.CopyToDataTable() : null;
        }
    }

在SelectedDate的setter中,调用获取网格值的代码。您还应该实现INotifyPropertyChanged,这样UI将更新数据,用户可以看到它。

首先,当您使用MVVM时,您必须通过实现INotifyPropertyChanged接口来通知您的属性


其次,在SelectedItem属性的设置程序中,您还必须通知WorkItems属性,这样当您从下拉列表中更改日期时,它还将更新DataGrid的ItemsSource。

您需要实现IOnPropertyChange接口。一旦您的组合框更改了值,您就必须应用过滤器并重新构建数据集。在您的代码中,组合框更新不起任何作用…接口INotifyPropertyChanged对我添加的输入错误表示抱歉:TimeTotalsDateSelectorViewModel:INotifyPropertyChanged公共事件属性ChangedEventHandler属性Changed;protected void OnPropertyChangedstring propertyName{if this.PropertyChanged!=null{this.PropertyChanged this,new PropertyChangedEventArgspropertyName;}}}还没有实际事件/侦听器,标签已停止更新……您是否实现了INotifyPropertyChanged?如果是,则从SelectedItems属性的setter对OnPropertyChanged方法进行两次调用。一个通过传递字符串SelectedItems,另一个通过传递字符串工作项