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.
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
.