sam*_*rem 4 c# mvvm reactive-programming system.reactive reactiveui
我有一个WPF MVVM应用程序.我的模型对象是我完全可以控制的POCO.这些对象中的某些属性之间存在关系.
例如:让我说我有
public class Model
{
public ObservableCollection<double> XCoordinates { get; set; } // Cumulative sum of DistancesBetweenXCoordinates.
public ObservableCollection<double> DistancesBetweenXCoordinates { get; set; } // {x[1]-x[0], x[2]-x[1], ..., x[n]-x[n-1]}
public double TotalLength { get; set; } // Sum of DistancesBetweenXCoordinates.
}
Run Code Online (Sandbox Code Playgroud)
我希望最终用户能够编辑距离列表或x坐标列表,其他属性应自动更新.到目前为止,我已经使用INPC事件完成了这项工作,但这很快就变得太乱了.一些UI更新在每个PropertyChange之后完成,所以我想优化它.
由于我的真实应用程序中的某些属性更新对性能影响不小,我不想使用"计算属性",例如
public double TotalLength => DistancesBetweenXCoordinates.Sum();
Run Code Online (Sandbox Code Playgroud)
根据我的阅读,ReactiveUI框架似乎具有我正在寻找的功能.我有一些问题:
1)我目前正在使用另一个框架(Catel),我宁愿完全放弃.我是否可以在.WhenAny()不继承的情况下使用ReactiveUI中的等等ReactiveObject(例如仅通过实现IReactiveObject)?
2)我见过的几乎所有例子都是ReactiveObject在ViewModel中继承的.这是实现我想要的首选方式吗?在我的模型中实现这个没有意义吗?如果我的模型应该只是一个"哑"的POCO而没有任何机制来保持所有相关属性的最新状态,那么这是我的Reactive VM的责任吗?
我会非常感谢一个简单的例子或其他指导.
INotifyPropertyChanged,你可以使用.WhenAny()ReactiveObject可以用于ViewModel和Model类.它实际上只是一个"反应"对象.即喜欢System.Object.(不相信我?查看来源.)ObservableAsPropertyHelper的计算性能依赖于其它反应性或事件.(见文档)有几种方法可以解决这个问题,但特别是你想要推理出几件事情:
ReactiveObject只限于ViewModels?它在普通的Model类中有用吗?首先,正如您已经注意到的那样,ReactiveUI的大部分内容都包含了强大的功能.WhenAny().你能在框架之间使用这些方法,是的!的.WhenAny(),.WhenAnyValue(),.WhenAnyObservable()方法上工作的任何一个实现目标INotifyPropertyChanged.(相关文件)
实际上,您的现有框架可能已经INotifyPropertyChanged在许多自己的类型上实现,因此.WhenAny()自然地扩展到无缝地处理这些对象.你几乎从来没有真正需要一个ReactiveObject.它只会让你的生活更轻松.
注意:这实际上是ReactiveUI的核心价值之一.在核心,ReactiveUI 实际上只是一堆扩展方法,旨在使现有.Net世界中的observable更容易使用.这使得与现有代码的互操作性成为ReactiveUI最引人注目的功能之一.
现在,应该ReactiveObject用于普通的"哑"模型吗?我想这取决于你想要承担责任的地方.如果你希望你的模型类只包含规范化状态而根本没有逻辑,那么可能不是.但是,如果您的模型旨在处理状态和域相关的逻辑,那么为什么不呢?
在这种情况下,我们关心通知监听器有关某些计算属性的更新,例如TotalLength.(即我们的模型包含一些逻辑)ReactiveObject帮助我们做到这一点?我认同.
在您的场景中,我们希望TotalLength在DistancesBetweenXCoordinates添加或更改元素或其他内容时计算.我们可以结合使用ReactiveObject和ObservableAsPropertyHelper.(相关文件)
例如:
class Model : ReactiveObject
{
// Other Properties Here...
// ObservableAsPropertyHelper makes it easy to map
// an observable sequence to a normal property.
public double TotalLength => totalLength.Value;
readonly ObservableAsPropertyHelper<double> totalLength;
public Model()
{
// Create an observable that resolves whenever a distance changes or
// gets added.
// You would probably need CreateObservable()
// to use Observable.FromEventPattern to convert the
// CollectionChanged event to an observable.
var distanceChanged = CreateObservable();
// Every time that a distance is changed:
totalLength = distanceChanged
// 1. Recalculate the new length.
.Select(distances => CalculateTotalLength(distances))
// 2. Save it to the totalLength property helper.
// 3. Send a PropertyChanged event for the TotalLength property.
.ToProperty(this, x => x.TotalLength);
}
}
Run Code Online (Sandbox Code Playgroud)
在上面,TotalLength每次distanceChangedobservable结算时都会重新计算.例如,这可以在DistanceBetweenXCoordinates发出CollectionChanged事件时发生.此外,因为这只是一个普通的可观察对象,您可以在后台线程上进行计算,从而允许您在长时间操作期间保持UI响应.计算完成后,将PropertyChanged发送事件TotalLength.
| 归档时间: |
|
| 查看次数: |
1271 次 |
| 最近记录: |