简体   繁体   English

检测绑定到 DataGrid 的集合(元素)中的更改,以更新 WPF (MVVM) 中的其他 collections

[英]Detect changes in (elements of) a collection bound to a DataGrid to update other collections in WPF (MVVM)

Responsive UI design: DataGrid inputs to cause changes automatically (MVVM)响应式 UI 设计: DataGrid输入自动引起更改 (MVVM)

I am trying to create a simple application in which I have a charting tool that accepts collections as series to be plotted.我正在尝试创建一个简单的应用程序,其中我有一个图表工具,它接受 collections 作为要绘制的系列。 My plan is to have an input DataGrid that is bound to a collection which can be populated manually.我的计划是有一个输入DataGrid绑定到可以手动填充的集合。

Based on the values inside the DataGrid , I would then like to simultaneously populate a different collection that represents the definite integral of whatever function is being plotted, in other words a different function that shows the area between the input function and the x-axis. Based on the values inside the DataGrid , I would then like to simultaneously populate a different collection that represents the definite integral of whatever function is being plotted, in other words a different function that shows the area between the input function and the x-axis.

As the DataGrid is updated, I would like to use MVVM to responsively update the chart as well, to display changes in both the input data and the output data.随着DataGrid的更新,我也想使用 MVVM 来响应更新图表,以显示输入数据和 output 数据的变化。

A. Application parts (mock-up and structure) A. 应用部分(模型和结构)

I have created a gist that contains my implementations so far . 到目前为止,我已经创建了一个包含我的实现的要点。

1. Main parts一、主要部件

In short, the application has the following components:简而言之,该应用程序具有以下组件:

  • Coordinate<T, U> that has an X and Y property (and uses INotifyPropertyChanged ) Coordinate<T, U>具有 X 和 Y 属性(并使用INotifyPropertyChanged
  • ObservableCollection<Coordinate<double, double>> for plotting purposes ObservableCollection<Coordinate<double, double>>用于绘图
  • NumericalCalculator for executing numerical methods用于执行数值方法的NumericalCalculator

2. Converters 2.转换器

In the WPF chatroom, Maverik suggested I could use value converters to let WPF do the heavy lifting, so I have written the following converters:在 WPF 聊天室中,Maverik 建议我可以使用值转换器让 WPF 完成繁重的工作,因此我编写了以下转换器:

  • CoordinateSeriesToStringConverter converts a collection of coordinates to a string where all the coordinates are separated by comma's CoordinateSeriesToStringConverter将坐标集合转换为字符串,其中所有坐标用逗号分隔
  • FunctionToEquallySpacedConverter attempts to convert a collection of coordinates into a new collection containing some n number of equally spaced coordinates FunctionToEquallySpacedConverter尝试将坐标集合转换为包含n个等距坐标的新集合
  • FunctionToIntegralConverter attempts to integrate the input function (collection of coordinates) to its numerical integral between two bounds (currently does not integrate yet, for testing purposes) FunctionToIntegralConverter尝试将输入 function(坐标集合)积分到其两个边界之间的数值积分(目前尚未积分,用于测试目的)

B. My actual question: How can I detect changes in the DataGrid 's items source's elements? B. 我的实际问题:如何检测DataGrid的项目源元素的变化?

I have gone the value converter route, but it turns out that even with INotifyPropertyChanged implemented on the elements of my bound ObservableCollection , those changes do not activate the converters.我已经走了值转换器路线,但事实证明,即使在绑定的ObservableCollection的元素上实现了INotifyPropertyChanged ,这些更改也不会激活转换器。

I've already gotten a nice answer from sparedev with a different approach, which I will likely try out as well, but I'm still curious how I could solve the value converter issue.我已经用另一种方法从sparedev得到了一个很好的答案,我也可能会尝试,但我仍然很好奇如何解决价值转换器问题。 I'm sure that if I get that sorted out, both options are equally viable.我敢肯定,如果我解决了这个问题,这两种选择都是同样可行的。

UPDATE: I've tried sparedev's method, but even with INotifyPropertyChanged , manipulating the DataGrid 's items from the UI does not raise any new events.更新:我尝试了备用开发的方法,但即使使用INotifyPropertyChanged ,从 UI 操作DataGrid的项目也不会引发任何新事件。 Adding new rows or deleting them raises a CollectionChanged event, but unfortunately this alone does not let me update the plots responsively yet.添加新行或删除它们会引发CollectionChanged事件,但不幸的是,仅此一项并不能让我响应地更新绘图。

Let's register on CollectionChanged event and update result collection, see below.让我们注册 CollectionChanged 事件并更新结果集合,见下文。

    public MainViewModel()
    {
      InputCollection.CollectionChanged += Items_CollectionChanged;
    }

    private void Items_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
      if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
      {
        foreach (var i in e.NewItems)
        {
          var c = i as Coordinate<double, double>;
          ResultCollection.Add(c);
          c.PropertyChanged += Item_PropertyChanged;
        }
      }

      if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove)
      {
        foreach (var i in e.OldItems)
        {
          var c = i as Coordinate<double, double>;
          ResultCollection.Remove(c);
          c.PropertyChanged += Item_PropertyChanged;
        }
      }
    }

    private void Item_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
      var c = sender as Coordinate<double, double>;
      Console.WriteLine(c.X + " " + c.Y);
    }

May be your Coordinate class should implement INotifyPropertyChanged interface.可能是您的坐标 class 应该实现 INotifyPropertyChanged 接口。 During setting X or Y property PropertyChanged should raised.在设置 X 或 Y 属性期间,应提高 PropertyChanged。

  public class Coordinate<T, U> : IComparable<Coordinate<T, U>>, INotifyPropertyChanged
    where T : IComparable<T>
    where U : IComparable<U>
  {
    public Coordinate() { }
    public Coordinate(T x, U y)
        => (X, Y) = (x, y);

    public event PropertyChangedEventHandler PropertyChanged;

    private T _X;
    public T X
    {
      get => _X;
      set
      {
        if (value.CompareTo(_X) != 0)
        {
          _X = value;
          PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(X)));
        }
      }
    }

    private U _Y;
    public U Y
    {
      get => _Y;
      set
      {
        if (value.CompareTo(_Y) != 0)
        {
          _Y = value;
          PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Y)));
        }
      }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM