Search code examples
mvvmuwp-xamlmodel-binding

ms mvvm toolkit: can't work out how to wire up ReplayCommand and canExecute


I have a simple model:

public sealed partial class ResultsModel : ObservableObject {

    [NotifyCanExecuteChangedFor(nameof(SaveCommand))]
    [NotifyCanExecuteChangedFor(nameof(ClearCommand))]
    [ObservableProperty]
    ObservableCollection<Arrivals> _arrivals = new();

    public RelayCommand SaveCommand { get; private set; }
    public RelayCommand ClearCommand { get; private set; }

    internal ResultsModel() {
        SaveCommand = new RelayCommand(SaveRequest, CanSaveClear);
        ClearCommand = new RelayCommand(OnClear, CanSaveClear);
    }

    public bool CanSaveClear() {
        return _arrivals.Count > 0;
    }

    void OnClear() {
        _arrivals.Clear();
    }

    async void SaveRequest() {
    // save stuff
    }
}

// c#
DataContext = (model = new ResultsModel());
...
model.Arrivals.insert(0, thing); 

// The _arrivals are bound to an ItemsRepeater and appear in gui as //they're added
<ItemsRepeater ItemsSource="{Binding Arrivals}">
<Button Content="Clear" Command="{Binding ClearCommand}"/>
<Button Content="Save" Command="{Binding SaveCommand}" />

I've bound buttons to the two Commands and they work ok, I just can't work how to get the canExecute code to run more than one time.

I was expecting that when items get added to the _arrivals collection (and they do) the canExecutes would be re-evaluated via the NotifyCanExecuteChangedFor attribute, but I'm obviously missing some glue somewhere because the button are always disabled.

Any help would be appreciated.


Solution

  • It won't happen when you added an item to the Arrivals. But it will happen when you change the Arrivals by giving a new ObservableCollection. You could create a simple string property to test this behavior.

    The reason for this behavior is that when the NotifyCanExecuteChangedFor Attribute is used, the IRelayCommand.NotifyCanExecuteChanged will be called when the setter of the property is called. In your scenario, that means only when the setter of the Arrivals property is called, this Attribute will call the IRelayCommand.NotifyCanExecuteChanged.