响应性UI设计:DataGrid
输入自动导致更改(MVVM)
我正在尝试创建一个简单的应用程序,在这个应用程序中,我有一个图表工具,它将集合接受为要绘制的系列。我的计划是有一个输入DataGrid
,它绑定到可以手动填充的集合。
根据DataGrid
中的值,我想同时填充一个不同的集合,它表示正在绘制的任何函数的定积分,换句话说,是一个不同的函数,它显示输入函数和x轴之间的区域。
在更新DataGrid
时,我希望使用MVVM响应地更新图表,以显示输入数据和输出数据中的更改。
A.应用部件(模拟和结构)
我创建了一个包含到目前为止我的实现的gist。
1.主要部分
简而言之,应用程序有以下组件:
Coordinate<T, U>
(并使用INotifyPropertyChanged
)ObservableCollection<Coordinate<double, double>>
NumericalCalculator
2.转换器
在WPF聊天室中,Maverik建议我可以使用值转换器让WPF完成繁重的工作,因此我编写了以下转换器:
CoordinateSeriesToStringConverter
将坐标集合转换为字符串,其中所有坐标都由逗号分隔FunctionToEquallySpacedConverter
试图将一个坐标集合转换为一个新集合,其中包含一些等距坐标的n
数。FunctionToIntegralConverter
试图将输入函数(坐标集合)集成到两个边界之间的数值积分(出于测试目的,目前尚未集成)。我的实际问题是:如何检测DataGrid
的项源元素中的更改?
我已经选择了值转换路由,但事实证明,即使在绑定的INotifyPropertyChanged
元素上实现了ObservableCollection
,这些更改也不会激活转换器。
我已经用一种不同的方法从sparedev
那里得到了一个很好的答案,我可能也会尝试,但我仍然好奇如何解决值转换问题。我敢肯定,如果我把这个问题解决了,两种选择都是同样可行的。
更新:我尝试过sparedev的方法,但即使使用INotifyPropertyChanged
,从UI中操作DataGrid
的项也不会引发任何新事件。添加新行或删除它们会引发CollectionChanged
事件,但不幸的是,仅这一点还不允许我对情节进行响应性更新。
发布于 2021-04-07 13:07:57
让我们在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);
}
可能是您的坐标类应该实现INotifyPropertyChanged接口。在设置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)));
}
}
}
}
https://stackoverflow.com/questions/66992997
复制相似问题