The problem is this.
You have a implementation of CanExecute , but no implementation of CanExecuteChanged . Therefore, changes to CanExecute not picked up.
There are several ways to solve this problem.
First, your implementation of RelayCommand (this is a non-standard class, which means that you take it from some framework or have written it yourself) may provide an opportunity to run CanExecuteChanged . Then you yourself must implement the logic that determines these circumstances, and " CanExecuteChanged " CanExecuteChanged at the right time. This path can be complicated if your parameter changes over time.
Secondly, you can, at the moment when, according to the logic of the program, a command can be activated or deactivated, you can manually call CommandManager.InvalidateRequerySuggested . After that, the value CanExecute will be re-read.
InvalidateRequerySuggested really didn't work on RelayCommand . I changed it to RoutedUICommand , and everything took off.
See it. First, we define the necessary command:
public class GlobalCommands : RoutedUICommand { private GlobalCommands() { } // запрещаем создавать экземпляры снаружи public static GlobalCommands ShowStudents = new GlobalCommands() { Text = "Отобразить список студентов" }; // сюда можно добавлять ещё команды }
Then, in the main VM create the CommandBinding :
public IEnumerable<CommandBinding> SupportedBindings { get { return supportedBindings; } } List<CommandBinding> supportedBindings; void InitCommands() { supportedBindings = new List<CommandBinding>() { new CommandBinding( GlobalCommands.ShowStudents, (sender, args) => ShowStudents(args.Parameter), (sender, args) => args.CanExecute = CanShowStudents(args.Parameter)) }; } // ... void ShowStudents(object iEvent) { if (iEvent is Event) { var _event = iEvent as Event; // загрузить конкретную группу } } bool CanShowStudents(object iEvent) { Debug.WriteLine("CanShowStudents called"); var ev = iEvent as Event; if (ev == null) return false; Debug.WriteLine($"CanShowStudents, persons = {ev.Persons}"); return Directory.Exists(AppPathGroups + @"\" + ev.Persons) && File.Exists(AppPathGroups + @"\" + ev.Persons + @"\" + "GroupList.dat"); }
This creates a team binding to its implementation.
Then, bindings need to be registered in order for some UI object to process them. For example, a window. To do this, in App.xaml.cs we write:
// вызывается на Application.Startup void ApplicationStartup(object sender, StartupEventArgs e) { var vm = new ViewModel(); foreach (var binding in vm.SupportedBindings) CommandManager.RegisterClassCommandBinding(typeof(Window), binding); var w = new Window1(); w.DataContext = vm; w.ShowDialog(); }
And finally, in the UI we write this:
<ContextMenu> <MenuItem Header="Отобразить список студентов" Command="{x:Static mvvm:GlobalCommands.ShowStudents}" CommandParameter="{Binding}"/> </ContextMenu>
In this embodiment, the code works.