The name "CommandManager" does not exist in the current context (Visual Studio 2015)

Trying to use the RelayCommand class below, I got an error: "The name" CommandManager "does not exist in the current context." According to this publication, the Class Library does not recognize the CommandManager class . I tried to solve the problem by adding an assembly called PresentationCore to Add Link. Unfortunately, no assembly assemblies were found on the device. I uninstalled Microsoft.NETCore.UniversalWindowsPlatform and reinstalled it as recommended in some posts, and I repaired Visual Studio, but that doesnโ€™t change anything. Is this my failure or is it a mistake? As a beginner, I am always inclined to think that I have forgotten something; -)

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Input; namespace MyApplication.Viewmodels { public class RelayCommand : ICommand { private readonly Action<object> _Execute; private readonly Func<object, bool> _CanExecute; public RelayCommand(Action<object> execute) : this(execute, null) { } public RelayCommand(Action<object> execute, Func<object, bool> canExecute) { if (execute == null) { throw new ArgumentNullException("execute", "Execute cannot be null."); } _Execute = execute; _CanExecute = canExecute; } public event EventHandler CanExecuteChanged { add { CommandManager.RequerySuggested += value; } remove { CommandManager.RequerySuggested -= value; } } public void Execute(object parameter) { _Execute(parameter); } public bool CanExecute(object parameter) { if (_CanExecute == null) { return true; } return _CanExecute(parameter); } } } 
+5
source share
4 answers

.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) { // this if clause is to prevent an infinity loop if (e.PropertyName != "CanExecute") { RefreshCommandStates(); } } public static void RefreshCommandStates() { for (var i = 0; i < _raiseCanExecuteChangedActions.Count; i++) { var raiseCanExecuteChangedAction = _raiseCanExecuteChangedActions[i]; if (raiseCanExecuteChangedAction != null) { raiseCanExecuteChangedAction.Invoke(); } } } } } 

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)); } } } } 
+3
source

You are mixing the standard .NET Framework WPF ( CommandManager ) and the smaller .NET Core Framework , which is used to develop UWP.

Unfortunately, they are not 100% compatible in all areas. You cannot use the RelayCommand class because it is written there - you will need to rewrite parts that rely on the CommandManager .

+2
source

When you create a class with a base (inherited) class, try opening the instance later:

  public class RelayCommand : ICommand { public RelayCommand() {} private readonly Action<object> _Execute; private readonly Func<object, bool> _CanExecute; public RelayCommand(Action<object> execute) : this(execute, null) { } 
0
source

This does not work on netstandard

I copied your code and I get

  public RelayCommand(Action<object> execute) : this(execute, null) { } 

"this" does not accept 2 parameters

and i also get this

 public class RelayCommand : ICommand { public RelayCommand() { } 

Does not implement ICommand -> CanExecuteChanged

So it won't work

-1
source

Source: https://habr.com/ru/post/1241432/


All Articles