We are migrating our WPF project from the MVVMLight library to the Microsoft CommunityToolkit library.
We went ahead following the shared Microsoft migration documentation and updated all our (about 1200) commands accordingly.
When we got the build afterwards, we noticed that the events were not triggered correctly in the project and the commands were not working.
However, the SetProperty() method does not run my RelayCommands.
Below we have resolved this issue for just one command of our user model. There are more then 100+ Models and 1200ish commands exist.
BaseViewModel.cs
public class BaseViewModel : ObservableObject, IDisposable
{
protected bool _disposed = false;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
public virtual void Dispose(bool disposing)
{
if (_disposed.Equals(false))
{
if (disposing)
{
}
_disposed = true;
}
}
private bool _isSaved;
public bool IsSaved
{
get { return _isSaved; }
set
{
SetProperty(ref _isSaved, value, nameof(_isSaved));
}
}
}
LoginViewModel
public class LoginViewModel : BaseViewModel
{
public LoginViewModel()
{
User = new UserModel();
User.PropertyChanged += User_PropertyChanged; // WHAT WE NEWLY ADDED
LoginCommand = new RelayCommand<Window>(OnLoginCommandExecuted, CanLoginCommandExecute);
CancelCommand = new RelayCommand<Window>(OnCancelCommandExecuted, CanCancelCommandExecute);
}
private void User_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (LoginCommand is not null) LoginCommand.NotifyCanExecuteChanged(); // We should notify it manually..
}
private UserModel _user;
public UserModel User
{
get { return _user; }
set
{
SetProperty(ref _user, value, nameof(_user));
}
}
public RelayCommand<Window>? LoginCommand { get; private set; }
public async void OnLoginCommandExecuted(Window window)
{
//DO STUFF
}
public bool CanLoginCommandExecute(Window window)
{
//DO STUFF
}
}
LoginWindow.xaml
<Window
x:Class="ProjectName.LoginWindow"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
x:Name="loginWindow">
<Button x:Name="btnLogin" Command="{Binding LoginCommand}" CommandParameter="{Binding ElementName=loginWindow}" />
</Window>
Is there any way to trigger NotifyCanExecuteChanged manager for all commands in active models?
What can i do in this situation? Does the following implementation need to be applied for all models and commands? Is this an expected situation? Thanks and happy codings.
EDIT: I changed whole project with annotations.
LoginViewModel
[ObservableProperty]
[NotifyCanExecuteChangedFor(nameof(LoginCommandExecutedCommand))]
private UserModel _user = new();
[RelayCommand(CanExecute = nameof(CanLoginCommandExecute))]
private async void OnLoginCommandExecuted(Window window)
{
//DO STUFF
}
private bool CanLoginCommandExecute(Window window)
{
// DO STUFF LOGIC
}
UserModel
[ObservableProperty]
private string _username;
partial void OnUsernameChanged(string value)
{
XtraMessageBox.Show("I HAVE CHANGED - USERNAME");
IsDirty = true;
}
[ObservableProperty]
private string _password;
partial void OnPasswordChanged(string value)
{
XtraMessageBox.Show("I HAVE CHANGED - PASSWORD");
IsDirty = true;
}
It fires the changes but notifying commands. Cause UserModel not changing. UserModels properties are changed.
That we can see model properties are changed.
And LoginViewModel's User Model updated.
But it is not executing my commands. Because its only GET'ing my UserModel, not setting. Autogenerated code only notify when UserModel sets.
What should i do?