0

I have a ReactiveCollection filled with Items (that are ReactiveObjects as well).

I want to create a ReactiveCommand that should be enabled only when any of the items in the collection has some property set to true, something like:

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

So anytime there is one of the items with the property set to true, the command should be enabled.

Edit

Thanks to the answerer. The resulting code is this:

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));

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

Edit 2

I've discovered a trap! If you modify this line:

new ItemViewModel("Engine");

and set the IsAdded = true like this

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

… when you run the button is disabled when the application starts and it should be enabled. It seems like the expression doesn't evaluate after some change occurs. How can I solve it?

halfer
  • 19,824
  • 17
  • 99
  • 186
SuperJMN
  • 13,110
  • 16
  • 86
  • 185
  • I've modified this such that the two Edit sections remain part of the question, since they are partial solutions. The full solution is basically a dup of Ana's question - I was going to post that as CW, but IMO it doesn't add anything new. – halfer Aug 13 '22 at 23:03

1 Answers1

2

How about this

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));
Ana Betts
  • 73,868
  • 16
  • 141
  • 209
  • I've added an issue to the original post. If the change that affects the observable happens before the creation of the command, it doesn't evaluate initially. Can you please review it? Thanks in advance! – SuperJMN Nov 21 '14 at 16:39
  • 1
    Updated! StartWith can solve some of these initial state problems – Ana Betts Nov 23 '14 at 01:11