0

How do I tell ReactiveUI to update bindings?

Normally, I would do something like this:

    string _instructorNameInput;
    public string InstructorNameInput
    {
        get { return _instructorNameInput; }
        set
        {
            this.RaiseAndSetIfChanged(ref _instructorNameInput, value);
            Submit.RaiseCanExecuteChanged();
        }
    }

However, the following isn't supported:

Submit.RaiseCanExecuteChanged();

As a result, how can I force bindings to update based on the CanExecute predicate that my command relies on?

Updated:

public partial class FormViewModel : ReactiveObject
{
    public FormViewModel()
    {
        Submit = ReactiveCommand.Create(this.WhenAnyValue(x => x.CanSubmit));
        Submit.Subscribe(x => OnSubmit());
    }

    bool _canExecute;
    public bool CanSubmit
    {
        get { return !GetUnsatisfied().Any(); }
        set { this.RaiseAndSetIfChanged(ref _canExecute, value); } // Need to update view based on command.CanExecute state change
    }
    void OnSubmit()
    {
        var rosterInfo = new RosterInfo(new Course(CourseInput.Name),
                                        new Instructor(InstructorNameInput, InstructorIdInput));
        var repository = GetRepository();
        repository.AddCourseInfo(rosterInfo);

        Publish(REQUEST_NAVIGATION_TO_SUBMITION_CONFIRMATION, rosterInfo);
    }

    ObservableCollection<RequiredField> GetUnsatisfied()
    {
        RequiredFields.Clear();
        RequiredFields = Review();
        return RequiredFields;
    }
}
Scott Nimrod
  • 11,206
  • 11
  • 54
  • 118
  • What is `Submit`? Is it a ReactiveCommand? – pmbanka Dec 17 '15 at 19:17
  • Yes. It's a ReactiveCommand. – Scott Nimrod Dec 17 '15 at 19:35
  • It is really unclear what is your problem. Could you please provide a complete view model code (with constructor, command, and property), and state clearly what behaviour you want to achieve, and what behaviour you observe in your program? – pmbanka Dec 17 '15 at 20:02
  • I updated the code example. I need my CanExecute to trigger a refresh on my view. DelegateCommand.RaiseCanExecuteChange() does this for me in Prism. However, I do not know how to do this using ReactiveUI. – Scott Nimrod Dec 17 '15 at 20:43

1 Answers1

2

Multiple issues:

Have a read at the fundamentals on ReactiveObject, in particular how "Read-Write Properties" are written.

In your case, this.WhenAnyValue(x => x.CanSubmit) will trigger a refresh on the command whenever the property CanSubmit changes, but this one never does, because you never call the setter (and the getter has an incorrect impl).

Currently, your method GetUnsatisfied() has "polling" semantics, which mean you need something to trigger this method to update your command. This isn't reactive at all, you should instead bind/listen to updates.

If there's no way for you to make your Review() logic reactive, then you may do something like:

var canExec = Observable.Timer(TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1))
                        .Select(_ => !GetUnsatisfied().Any());
Submit = ReactiveCommand.Create(canExec);
Submit.Subscribe(x => OnSubmit());

Basically, having a timer to do your polling. (But I strongly suggest going further down the reactive way)

Lennart
  • 9,657
  • 16
  • 68
  • 84
Gluck
  • 2,933
  • 16
  • 28