ReactiveCommand CanExecute对集合中的更改做出反应

时间:2014-10-31 17:04:52

标签: mvvm reactive-programming reactiveui

我有一个ReactiveCollection填充了Items(也是ReactiveObjects)。

我想创建一个ReactiveCommand,只有当任何集合中的项目的某些属性设置为true时才应启用它,如:

MyCommand = ReactiveCommand.Create( watch items in collection to see if item.MyProp == true ) 

因此,只要其中一个属性设置为true的项目,就应该启用该命令。

修改 谢谢,保罗。结果代码如下:

public MainViewModel()
{
    Items = new ReactiveList<ItemViewModel>
                {
                    new ItemViewModel("Engine"),
                    new ItemViewModel("Turbine"),
                    new ItemViewModel("Landing gear"),
                    new ItemViewModel("Wings"),
                };

    Items.ChangeTrackingEnabled = true;

    var shouldBeEnabled = Items.CreateDerivedCollection(x => x.IsAdded);

    var shouldRecheck = Observable.Merge(
        // When items are added / removed / whatever
        shouldBeEnabled.Changed.Select(_ => Unit.Default),
        // When any of the bools in the coll change
        shouldBeEnabled.ItemChanged.Select(_ => Unit.Default));

    // Kick off a check on startup
    shouldRecheck = shouldRecheck.StartWith(Unit.Default);

    ClearCommand = ReactiveCommand.Create(shouldRecheck.Select(_ => shouldBeEnabled.Any(x => x)));
}

编辑2: 我发现了一个陷阱!如果您修改此行:

new ItemViewModel("Engine");

并像这样设置IsAdded = true

new ItemViewModel("Engine") { IsAdded = true };

...当您运行按钮时,应用程序启动时禁用该按钮,应启用该按钮。在某些变化发生后,似乎表达式并未进行评估。我该如何解决?

编辑3:解决了!正如@ paul-betts所说,添加这一行可以解决这个问题:

// Kick off a check on startup
shouldRecheck = shouldRecheck.StartWith(Unit.Default);

代码示例也在上面更新(也在他的回答中)。

1 个答案:

答案 0 :(得分:2)

这个怎么样

mySourceCollection.ChangeTrackingEnabled = true;
shouldBeEnabled = mySourceCollection.CreateDerivedCollection(x => x.MyProp);

var shouldRecheck = Observable.Merge(
    // When items are added / removed / whatever
    shouldBeEnabled.Changed.Select(_ => Unit.Default),

    // When any of the bools in the coll change
    shouldBeEnabled.ItemChanged.Select(_ => Unit.Default));

// Kick off a check on startup
shouldRecheck = shouldRecheck.StartWith(Unit.Default);

myCmd = ReactiveCommand.Create(shouldRecheck.Select(_ => shouldBeEnabled.All(x => x));