.NETCore lacks CommandManager. I wrote my own interpretation because I was in the same situation as now. (UWP application development with MVVM design pattern)
RelayCommand.cs:
using System; using System.Windows.Input; namespace MVVMBoostUniversalWindowsApp { public class RelayCommand : ICommand { private readonly Action execute; private readonly Func<bool> canExecute; public RelayCommand(Action execute) : this(execute, null) { } public RelayCommand(Action execute, Func<bool> canExecute) { if (execute == null) throw new ArgumentNullException("execute is null."); this.execute = execute; this.canExecute = canExecute; this.RaiseCanExecuteChangedAction = RaiseCanExecuteChanged; SimpleCommandManager.AddRaiseCanExecuteChangedAction(ref RaiseCanExecuteChangedAction); } ~RelayCommand() { RemoveCommand(); } public void RemoveCommand() { SimpleCommandManager.RemoveRaiseCanExecuteChangedAction(RaiseCanExecuteChangedAction); } bool ICommand.CanExecute(object parameter) { return CanExecute; } public void Execute(object parameter) { execute(); SimpleCommandManager.RefreshCommandStates(); } public bool CanExecute { get { return canExecute == null || canExecute(); } } public void RaiseCanExecuteChanged() { var handler = CanExecuteChanged; if (handler != null) { handler(this, new EventArgs()); } } private readonly Action RaiseCanExecuteChangedAction; public event EventHandler CanExecuteChanged; } }
and here is my SimpleCommandManager.cs:
using System; using System.Collections.Generic; using System.ComponentModel; namespace MVVMBoostUniversalWindowsApp { public static class SimpleCommandManager { private static List<Action> _raiseCanExecuteChangedActions = new List<Action>(); public static void AddRaiseCanExecuteChangedAction(ref Action raiseCanExecuteChangedAction) { _raiseCanExecuteChangedActions.Add(raiseCanExecuteChangedAction); } public static void RemoveRaiseCanExecuteChangedAction(Action raiseCanExecuteChangedAction) { _raiseCanExecuteChangedActions.Remove(raiseCanExecuteChangedAction); } public static void AssignOnPropertyChanged(ref PropertyChangedEventHandler propertyEventHandler) { propertyEventHandler += OnPropertyChanged; } private static void OnPropertyChanged(object sender, PropertyChangedEventArgs e) {
Do not ask me why there is no CommandManager in .NETCore, I donโt know / donโt know either. If someone can provide some information regarding this, it would be great to know.
But you have to take care of use: if you leave the page, you must destroy the remaining commands in SimpleCommandManager, which are no longer used, but mentioned. I also have a solution for this, if necessary, I could edit my post.
This is really just a very simple / primitive solution and nothing special. But it works.
EDIT:
To provide a better use case and base, here is my basic ViewModel. As mentioned above, when you exit the current page, you should call "RemoveCommands". Otherwise, they will never be released by the GC.
ViewModel.cs
using System.ComponentModel; using System; using System.Runtime.CompilerServices; using Windows.UI.Xaml.Controls; using System.Collections.Generic; using Windows.UI.Core; namespace MVVMBoostUniversalWindowsApp { public abstract class ViewModel : INotifyPropertyChanged { protected ViewModel() { DispatcherObject = CoreWindow.GetForCurrentThread().Dispatcher; SimpleCommandManager.AssignOnPropertyChanged(ref this.PropertyChanged); _commandsList = new List<RelayCommand>(); } private List<RelayCommand> _commandsList; protected RelayCommand CreateCommand(Action execute) { return CreateCommand(execute, null); } protected RelayCommand CreateCommand(Action execute, Func<bool> canExecute) { var tempCmd = new RelayCommand(execute, canExecute); if (_commandsList.Contains(tempCmd)) { return _commandsList[_commandsList.IndexOf(tempCmd)]; } else { _commandsList.Add(tempCmd); return tempCmd; } } public void RemoveCommands() { for (var i = 0; i < _commandsList.Count; i++) { _commandsList[i].RemoveCommand(); } } public virtual CoreDispatcher DispatcherObject { get; protected set; } public event PropertyChangedEventHandler PropertyChanged; protected void ChangeProperty<T>(ref T property, T value, [CallerMemberName] string propertyName = null) { if (Object.Equals(property, value)) { return; } else { property = value; OnPropertyChanged(propertyName); } } protected void OnPropertyChangedEmpty() { OnPropertyChanged(String.Empty); } protected void OnPropertyChanged(string propertyName) { var handler = PropertyChanged; if (handler != null) { handler(this, new PropertyChangedEventArgs(propertyName)); } } } }