我正在开发一个小程序,我正在评估反应式ui是否是另一个项目的正确框架。到目前为止一直都很好......目前我在DynamicData相关功能中有点迷失。每次更改ReactiveUserControl中的组合框时,我都会尝试在MainViewWindow中执行命令。我的所有模型都在扩展ReactiveObject,并使用RaiseAndSetIfChanged setter设置属性。
在我的ReactiveUserControl ViewModel中,我从ReactiveUserControl ViewModel调用我的Command SaveImage,如下所述:https://reactiveui.net/docs/handbook/message-bus/#ways-to-avoid-using-messagebus
定义ObservableCollection
public ObservableCollection<FileViewModel> VisibleFiles { get; protected set; }
初始化集合,文件是SourceList
WatchFiles = ReactiveCommand.Create(() =>
{
VisibleFiles = new ObservableCollection<FilesViewModel>(Files.Items);
VisibleFiles.ToObservableChangeSet().AutoRefreshOnObservable(doc => doc.SaveImage).Select(_ => WhenAnyFileChanged()).Switch().Subscribe<FilesViewModel>(x => {
Console.WriteLine("HOORAY");
});
});
private IObservable<FilesViewModel> WhenAnyFileChanged()
{
return VisibleFiles.Select(x => x.SaveFile.Select(_ => x )).Merge();
}
组合框第一次更改时,它被评估为正确。我得到了“万岁”。但每次之后都没有输出。如果我再次调用Watch Files Command它再次工作一次。为什么会发生这种情况,如何在每次文件更改“Hooray”时解决它?我可以看到,ObservableCollection检测到更改,并且还在更改时调用ReactiveUserControl中的Command。但是,在第一次调用之后,WhenAnyFileChanged方法不会返回已更改的元素。希望我想要实现的目标是可以理解的,这就是问题所在。
更新:我不知道为什么,但如果我检查Select()中的ChangeSet,我会在初始化时获得TotalChanges 10,这是正确的。然后我的第一次工作更改TotalChanges为0,但评估正确。在我下次尝试更改时,我仍然获得0 TotalChanges但在WhenAnyFileChanged()中也没有正确的评估。每次更改时刷新()为1。
更新2:将AutoRefresh Observable()更改为Auto Refresh()会带来所需的功能。
我复制了原始的消息总线示例并编写了一个单元测试,以查看代码是否按预期运行。我可以确认您看到的问题出现在示例中。以下代码仅触发一次。
public MainViewModel()
{
OpenDocuments = new ObservableCollection<DocumentViewModel>();
OpenDocuments
.ToObservableChangeSet()
.AutoRefreshOnObservable(document => document.Close)
.Select(_ => WhenAnyDocumentClosed())
.Switch()
.Subscribe(x => OpenDocuments.Remove(x), ex=>{},()=>{});
}
IObservable<DocumentViewModel> WhenAnyDocumentClosed()
{
return OpenDocuments
.Select(x => x.Close.Select(_ => x))
.Merge();
}
这是证明它的测试。它第二次尝试删除失败。
[Fact]
public void MyTest()
{
//I added an id field to help with diagnostics / testing
_mainViewModel.OpenDocuments.Count.Should().Be(4);
_mainViewModel.OpenDocuments.Any(dvm => dvm.Id == "1").Should().BeTrue();
_mainViewModel.OpenDocuments[0].Close.Execute().Subscribe();
_mainViewModel.OpenDocuments.Count.Should().Be(3);
_mainViewModel.OpenDocuments.Any(dvm => dvm.Id == "1").Should().BeFalse();
_mainViewModel.OpenDocuments[0].Close.Execute().Subscribe();
_mainViewModel.OpenDocuments.Count.Should().Be(2);
_mainViewModel.OpenDocuments.Any(dvm => dvm.Id == "2").Should().BeFalse();
}
我不确定为什么会失败,但最理想的解决方法是使用动态数据的MergeMany
运算符,它类似于Rx的Merge
,但是当项目被添加到基础列表时会自动连接可观察数据,并在项目被删除时自动连接它们。修复是:
public class MainViewModel : ReactiveObject
{
public ObservableCollection<DocumentViewModel> OpenDocuments { get;}
public MainViewModel()
{
OpenDocuments = new ObservableCollection<DocumentViewModel>();
OpenDocuments
.ToObservableChangeSet()
.MergeMany(x => x.Close.Select(_ => x))
.Subscribe(x => OpenDocuments.Remove(x));
}
}
运行相同的单元测试通过。
单元测试的代码可用in this gist