How to call ICommand.CanExecute in this case?
.net, c#, mvvm, wpf, xaml
Solution
I want to know if this architecture correct and in line with MVVM pattern?
Yeah, that's completely in compliance with MVVM pattern.
Who calls CanExecute() and when?
CanExecute() gets called whenever `CanExecuteChanged` event is raised.
Commands internally hooks to this event and enable/disable button or any frameworkElement based on bool property returned by CanExecute delegate.
How can I call it manually?
First of all create `RaiseCanExecuteChanged()` method in your concrete implementation (if not already) so that it can be called manually. This will look like this:
public void RaiseCanExecuteChanged()
{
EventHandler canExecuteChangedHandler = CanExecuteChanged;
if (canExecuteChangedHandler != null)
{
canExecuteChangedHandler(this, EventArgs.Empty);
}
}
Since in your case, you need to call `CanExecute()` whenever SelectedItem in dataGrid changes. I would suggest to bind `SelectedItem` of DataGrid to some property in your ViewModel and in setter, you manually call `RaiseCanExecuteChanged()` so that CanExecute can be called on your command instance.
However, there is another way if you don't want to manually call `RaiseCanExecuteChanged()` method. You can hook to `CommandManager.RequerySuggested` event which gets raised whenever `CommandManager` feels like that UI needs to be refreshed.
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
RequerySuggested event Occurs when the System.Windows.Input.CommandManager detects conditions that might change the ability of a command to execute.
So, whenever `CommandManager.RequerySuggested` gets raised, it will eventually raises your `CanExecuteChanged` thereby calling `CanExecute` of your command. Hence enable/disable button based on bool returned by CanExecute delegate.
Problem
OK. Here's the scenario. This is WPF + MVVM (.net 4.0) application: - View: Has a `DataGrid` and two buttons Move Up / Move Down, which are supposed to move selected record up or down in the `DataGrid`. Both the grid and the buttons use XAML-based binding. - ViewModel: Has a public property of `DataView` type to which my `DataGrid` will bind. Then there are two `ICommand` implementations listed below. The two buttons will bind to these two commands. Last but not the least there are two functions called `MoveUp()` and `MoveDown()` that do the obvious. - Two `ICommand` implementations: In each command, `CanExecute()` returns whether selected record can be moved up or down respectively, and `Execute()` actually moves the record by calling ViewModel's `MoveUp()` and `MoveDown()` functions I described above. These command objects get a reference of VM object in their constructors. First off, I want to know if this architecture correct and in line with MVVM pattern? Secondly, the problem at hand is that my buttons do not get enabled/disabled when I change selected record in the `DataGrid`, which brings up 2 sub-questions: - Who calls `CanExecute()` and when? - How can I call it manually? I have tried `CommandManager.InvalidateRequerySuggested()` after reading some other SO questions, but that didn't help either. Here's my `CommandBase` class, from which both my Command classes inherit: ``` internal abstract class CommandBase : DependencyObject, ICommand { public virtual bool CanExecute(Object parameter) { return true; } public abstract void Execute(Object parameter); public event EventHandler CanExecuteChanged; protected void OnCanExecuteChanged(Object sender, EventArgs e) { CanExecuteChanged(sender, e); } } ```