mvvmgen
mvvmgen copied to clipboard
Raise CommandInvalidate when adding or removing elements on collection
Hello Thomas.
Is it possible to raise a CommandInvalidate method when changing the number of elements on an ObservableCollection?
In my code i have an ObservableCollection where i can add or remove elements via command methods. Now I want to implement a clear button which will become enabled when the ObservableCollection has more than zero elements.
[ViewModel]
[ViewModelGenerateFactory]
public partial class VM_ParameterChooser
{
[Property] ObservableCollection<VM_Parameter> selectedParameterList = new ObservableCollection<VM_Parameter>();
[Command(CanExecuteMethod = nameof(SelectedListCanBeCleared))]
public void Clear()
{
SelectedParameterList.Clear();
}
//this method is only called when SelectedParameterList is changed itself
//but should be called if a element is added or removed from the collection
[CommandInvalidate(nameof(SelectedParameterList))]
public bool SelectedListCanBeCleared() => SelectedParameterList.Count > 0;
[Command]
public void AddSelectedParameter(object param)
{
var selectedParam = param as VM_Parameter;
if (selectedParam is null) return;
SelectedParameterList.Add(selectedParam);
}
[Command]
public void RemoveSelectedParameter(object param)
{
var selectedParam = param as VM_Parameter;
if (selectedParam is null) return;
SelectedParameterList.Remove(selectedParam);
}
}
Hi,
Two things come to my mind what you could do here. Call 'ClearCommand.RaiseCanExecuteChanged();' at the end of your Add and Remove method or overwrite the OnInitialize method and subscribe to the 'CollectionChanged' event of your selectedParameterList and if fired call the 'ClearCommand.RaiseCanExecuteChanged();' .
Hey @Telespaz
Thank you for your answer.
Call 'ClearCommand.RaiseCanExecuteChanged();' at the end of your Add and Remove method
Yep, i added a call to my Add and Remove Method and the button enables and disables as expected.
InvalidateCommands(nameof(SelectedParameterList));
@Daimonion1980 This sounds like a great approach that you took now.
Alternatively, you can call as suggested by @Telespaz
ClearCommand.RaiseCanExecuteChanged();
But in your case, your call to InvalidateCommands
might be more clear from a semantical point of view. Both ways are good. 👍
Your idea is great to include this in MvvmGen, but it gets super complex very soon. The items in the ObservableCollection could be INotifyPropertyChanged objects, then you need to track these changes as well etc. I think handling it in your own code is the best way, as the generator might lead to a 90% solution.
Btw, if you don't set the ObservableCollection to a new instance from your UI, there's no reason to use a field with the Property
attribute. Instead, you can define the property directly in your code like this (I included a bit of C# 12 sugar, the []
to initialize the collection 😊):
[ViewModel]
[ViewModelGenerateFactory]
public partial class VM_ParameterChooser
{
public ObservableCollection<VM_Parameter> SelectedParameterList = [];
[Command(CanExecuteMethod = nameof(SelectedListCanBeCleared))]
public void Clear()
{
SelectedParameterList.Clear();
}
[CommandInvalidate(nameof(SelectedParameterList))]
public bool SelectedListCanBeCleared() => SelectedParameterList.Count > 0;
[Command]
public void AddSelectedParameter(object param)
{
var selectedParam = param as VM_Parameter;
if (selectedParam is null) return;
SelectedParameterList.Add(selectedParam);
InvalidateCommands(nameof(SelectedParameterList));
}
[Command]
public void RemoveSelectedParameter(object param)
{
var selectedParam = param as VM_Parameter;
if (selectedParam is null) return;
SelectedParameterList.Remove(selectedParam);
InvalidateCommands(nameof(SelectedParameterList));
}
}