Does the [NotifyCanExecuteChangedFor] Annotation Not Work in Combination with ObservableCollection?

26 Views Asked by At

I've noticed odd behaviour in my .NET MAUI application regarding the use of NotifyCanExecuteChangedFor in combination with ObservableCollection.

Here is the premise: My UI is the following:

UI Image

Of importance to this question are the upper right buttons with the reading "Standard", "Multiple" and "Entry", and the lower buttons "Add Answer" in the left corner and "Remove last Answer" in the right corner.

If one is clicking the "Add answer" button, an additional answer is added to the CollectionView in the lower grey box:

UI Image after clicking "Add answer" Button

Now, the CollectionView in the UI is bound to an ObservableCollection in the corresponding ViewModel, as in the following:

[ObservableProperty]
[NotifyCanExecuteChangedFor(nameof(AddAnswerCommand))]
[NotifyCanExecuteChangedFor(nameof(RemoveLastAnswerCommand))]
private ObservableCollection<Answer> _answers = new();

The corresponding functions are found below:

[RelayCommand(CanExecute = nameof(CanAddAnswer))]
private void OnAddAnswer()
{
    AddEmptyAnswerToAnswers();
}

[RelayCommand(CanExecute = nameof(CanRemoveLastAnswer))]
private void OnRemoveLastAnswer()
{
    var lastIndex = Answers.Count-1;
    Answers.RemoveAt(lastIndex);
}

private bool CanAddAnswer()
{
    return Answers.Count < 6;
}

private bool CanRemoveLastAnswer()
{
    return Answers.Count > 1;
}

The odd behaviour is on the one hand, the "Remove last answer" button is not notified of the change.

On the other hand, when one is pressing either "Standard", "Multiple" or "Entry" button, the "Remove last answer" button seems to update accordingly:

enter image description here

The upper three buttons are essentially bound to the field "QuestionType", as in the following:

[ObservableProperty]
[NotifyCanExecuteChangedFor(nameof(AddAnswerCommand))]
[NotifyCanExecuteChangedFor(nameof(RemoveLastAnswerCommand))]
[NotifyCanExecuteChangedFor(nameof(SwitchToStandardCommand))]
[NotifyCanExecuteChangedFor(nameof(SwitchToMultipleCommand))]
[NotifyCanExecuteChangedFor(nameof(SwitchToEntryCommand))]
private int _questionType = 0;

//...

[RelayCommand(CanExecute = nameof(CanSwitchToStandard))]
private void OnSwitchToStandard()
{
    QuestionType = 0;
}

[RelayCommand(CanExecute = nameof(CanSwitchToMultiple))]
private void OnSwitchToMultiple()
{
    QuestionType = 1;
}

[RelayCommand(CanExecute = nameof(CanSwitchToEntry))]
private void OnSwitchToEntry()
{
    QuestionType = 2;
}

private bool CanSwitchToStandard()
{
    return QuestionType != 0;
}

private bool CanSwitchToMultiple()
{
    return QuestionType != 1;
}

private bool CanSwitchToEntry()
{
    return QuestionType != 2;
}

My question now is, why is it working then? Why is the button "Remove last answer" not notified of changes in the ObservableCollection but as soon as one of the upper buttons is used, the notification via the "QuestionType" property is properly delivered?

I've tried to change and rearrange the [NotifyCanExecuteChangedFor] annotation. However, I also have trouble finding documentation of specifically those annotations.

1

There are 1 best solutions below

0
User2363562 On

Thanks to @Jason I found a simple Answer:

Adding an event handler in the class constructor solved the issue:

Answers.CollectionChanged += (sender, e) =>
{
    AddAnswerCommand.NotifyCanExecuteChanged();
    RemoveLastAnswerCommand.NotifyCanExecuteChanged();
};