[英]Detect changes in (elements of) a collection bound to a DataGrid to update other collections in WPF (MVVM)
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 数据的变化。
I have created a gist that contains my implementations so far . 到目前为止,我已经创建了一个包含我的实现的要点。
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
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(坐标集合)积分到其两个边界之间的数值积分(目前尚未积分,用于测试目的)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.