问题
I wanted to have my DataGrids with a context menu that allows the user to move the selected rows up or down. After some search, I've come up with the following code that has a problem. It seems that CanExecute is only called once (I guess when the menu gets created), so my MenuItem will either be enabled or disabled all of the time. What I am struggling to achieve is to make it enabled when there are rows selected in the DataGrid and disabled when there aren't any. Currently this doesn't work.
Also, is there a more elegant solution to this? If I use more code I think it will become a huge mess...
public class DataGridMoveRowsUpCommand : ICommand
{
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter)
{
var grid = parameter as DataGrid;
if (grid != null && grid.SelectedItems.Count > 0) return true;
return false;
}
public void Execute(object parameter)
{
// Do sth...
}
public void RaiseCanExecuteChanged()
{
if (CanExecuteChanged != null) CanExecuteChanged(this, EventArgs.Empty);
}
}
//-------------------------------------------------------------
public class MyDataGrid : DataGrid
{
public static ICommand DataGridMoveRowsUp
{
get { return new DataGridMoveRowsUpCommand(); }
}
}
//-------------------------------------------------------------
<kbm:MyDataGrid x:Name="gridExpenses" ContextMenu="{StaticResource DataGridContextMenu}"/>
//-------------------------------------------------------------
<ContextMenu x:Key="DataGridContextMenu" x:Shared="true">
<MenuItem Header="{DynamicResource StringMoveUp}"
Command="kbm:MyDataGrid.DataGridMoveRowsUp"
CommandTarget="{Binding Path=PlacementTarget, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}}"
CommandParameter="{Binding Path=PlacementTarget, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}}">
</MenuItem>
...
回答1:
You have to manually called RaiseCanExecuteChanged method whenever you feel like that command needs to be revaluated. (Most probably in case SelectedItems of dataGrid gets changed.)
OR
Either you can let CommandManager decides when to raise CanExecuteChanged event of your command by hooking onto RequerySuggested event of CommandManager like this:
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
RequerySuggestedevent Occurs when the System.Windows.Input.CommandManager detects conditions that might change the ability of a command to execute.
来源:https://stackoverflow.com/questions/21585518/wpf-canexecute-doesnt-work-for-datagrids-contextmenu