I have the following piece of code:
ReactiveCommand
.CreateFromTask(_ => GetPerson())
.Execute()
.Subscribe(x => person = x);
var canNext = person?.Friends
.ToObservableChangeSet()
.AutoRefresh(x => x.Selected)
.ToCollection()
.Select(x => x.Any(y => y.Selected));
MyCommand = ReactiveCommand.CreateFromTask(async _ => Debug.Write("Hello"), canNext);
How can I get canNext
to update in order to disable/enable my command?
If I hard code a person
with friends
the canNext
works fine when selecting and deselecting friends. However when assigning person
to an async
call GetPerson()
it breaks any updates running to canNext
.
I've created a dummy project to help demo the problem. https://github.com/grierson/updateButton
To get the behavior you want you could first initialize person
, and then when you call GetPerson()
, just update the person
you already have, as follows
person = new Person() { Friends = new ObservableCollection<Friend>() };
ReactiveCommand
.CreateFromTask(_ => GetPerson())
.Execute()
.Subscribe(x =>
{
foreach (var friend in x.Friends)
{
person.Friends.Add(friend);
}
});
var canNext = person?.Friends
.ToObservableChangeSet()
.AutoRefresh(x => x.Selected)
.ToCollection()
.Select(x => x.Any(y => y.Selected));
MyCommand = ReactiveCommand.CreateFromTask(async _ => Debug.Write("Hello"), canNext);
Now some words about what you are doing wrong:
The reason for this behavior is that when you run
ReactiveCommand
.CreateFromTask(_ => GetPerson())
.Execute()
.Subscribe(x => person = x);
var canNext = person?.Friends
.ToObservableChangeSet()
.AutoRefresh(x => x.Selected)
.ToCollection()
.Select(x => x.Any(y => y.Selected));
MyCommand = ReactiveCommand.CreateFromTask(async _ => Debug.Write("Hello"), canNext);
at the moment you reach the line that sets MyCommand
, the value of canNext
is null
: this happens because person
is null
at that point of time, and so you are passing a null
value to the canExecute
parameter of CreateFromTask
, i.e. you are really setting
MyCommand = ReactiveCommand.CreateFromTask(async _ => Debug.Write("Hello"), null);
or what is the same
MyCommand = ReactiveCommand.CreateFromTask(async _ => Debug.Write("Hello"));
that is, you are not really passing any information to canExecute
, and the Button
is simply always active, as you can see when you run the code above.
P.S.: Thanks for the simple sample. It was key on being able to find out the root of the problem.