问题描述
这是我当前的设置:
public class MainWindowviewmodel : ReactiveObject
{
public FullBuildModel FullBuild { get; } = new FullBuildModel();
public ICommand RecalculateSolverCommand { get; }
}
public class FullBuildModel : ReactiveObject
{
PlayerClass @class;
public PlayerClass Class { get => @class; set => this.RaiseAndSetIfChanged(ref @class,value); }
readonly ObservableAsPropertyHelper<PlayerMasterySkillWithCountModel[]> skillsWithCount;
public PlayerMasterySkillWithCountModel[] SkillsWithCount => skillsWithCount.Value;
}
public class PlayerMasterySkillWithCountModel : ReactiveObject
{
int allocated;
public int Allocated { get => allocated; set => this.RaiseAndSetIfChanged(ref allocated,value); }
}
public class PlayerSkill
{
}
我的绑定代码如下:
this.WhenActivated(dc =>
{
viewmodel.FullBuild.WhenAnyValue(x => x.SkillsWithCount)
.Subscribe(skillsWithCount => skillsWithCount
.Select(w => w.ObservableForProperty(m => m.Allocated).Select(_=>System.Reactive.Unit.Default)).Amb()
.InvokeCommand(viewmodel.RecalculateSolverCommand)
.disposeWith(dc))
.disposeWith(dc);
});
这个想法是,每当一项技能的分配计数发生变化时,我都想运行recalculate命令。 Amb()
使我离我很近,但是由于某种原因,它仅在第一次更改时触发。根据官方文档,我也尝试过CombineLatest()
,但此事一无所获。
如何将可观察的可枚举合并为可用于调用命令的可观察的一个?我不在乎是哪个触发的,我只是在乎其中的一个触发了。我想我可以遍历数组,并在每个项目上单独运行一个WhenAnyValue
并将其映射到我的命令,但是我是如此接近,以至于有是一种更好的方法。 / p>
解决方法
您必须弄平数组,订阅每个项目,然后将结果合并到单个流中。嵌套的Select帮助解决了这一部分。下面的代码段中引用的IObservable<int>
是一个WhenAnyValue
属性,它是从Allocated属性的ViewModel.FullBuild.WhenAnyValue(x => x.SkillsWithCount)
.Select(x => x.Select(y => y.AllocatedStream).Merge())
.Switch()
.Select(_ => Unit.Default)
.InvokeCommand(ViewModel.RecalculateSolverCommand)
.DisposeWith(dc);
创建的。将子级合并为一个流之后,Switch会确保在订阅新元素之前(当SkillsWithCount被重新分配时)所有这些子级订阅都已处置。
{{1}}
这假定您不对数组进行突变(例如SkillsWithCount [i] = someOtherObject),因为那样您就必须自行处理退订旧元素的问题。