Reputation: 5534
I'm binding a control to a DelegateCommand and the CanExecute portion of it is not working properly. I am using the Prism libraries. Can anyone tell me why?
Command declaration and instantiation:
public PlayerManagementViewModel(DatabaseManager dbManager)
{
_dbManager = dbManager;
this.ResetUpToDateStatusCommand = new DelegateCommand(() => this.ResetXpUpToDateStatus());
this.DeletePlayerCommand = new DelegateCommand(() => this.DeleteSelectedPlayer(), () => SelectedPlayer != null);
this.RefreshPlayers();
}
public ICommand DeletePlayerCommand { get; private set; }
SelectedPlayer definition:
public Player SelectedPlayer
{
get { return _selectedPlayer; }
set
{
SetProperty(ref this._selectedPlayer, value);
this.OnPropertyChanged(() => this.FormattedPlayerStatus);
}
}
The weird thing is that if you look at the line above the DeletePlayerCommand
instantiation, that line works just fine. I don't get any CanExecute
behavior out of it, but at least it works. As is, the DeletePlayerCommand
command never fires off, even with a breakpoint, unless I remove the CanExecute portion of the constructor entirely.
Can anyone please explain to me why this is or what I'm doing wrong?
Upvotes: 1
Views: 5157
Reputation: 5366
It is the way PRISM DelegateCommnd is designed. refer CanExecuteChanged event of ICommand.
Alternatively you can derive the DelegateCommand to overcome the limitation. refer the below code.
class DelegateCmdEx : DelegateCommand
{
public DelegateCmdEx(Action executeMethod):base(executeMethod)
{
}
public DelegateCmdEx(Action executeMethod, Func<bool> canExecuteMethod)
: base(executeMethod, canExecuteMethod)
{
}
public override event EventHandler CanExecuteChanged
{
add
{
CommandManager.RequerySuggested += value;
}
remove
{
CommandManager.RequerySuggested -= value;
}
}
}
Upvotes: 0
Reputation: 18126
If the CanExecute
function of the DeletePlayerCommand
is () => SelectedPlayer != null
, then there must be a DelegateCommandBase.RaiseCanExecuteChanged Method call when SelectedProperty
value is changed:
Raises CanExecuteChanged on the UI thread so every command invoker can requery to check if the command can execute.
The appropriate UI-element (with data-bound command) is a command invoker.
To summarize, the implementation of the SelectedPlayer
property should be updated as follows:
class PlayerManagementViewModel : BindableBase
{
private Player _selectedPlayer;
private readonly DelegateCommand _deletePlayerCommand;
public PlayerManagementViewModel(...)
{
_deletePlayerCommand = new DelegateCommand(() => DeleteSelectedPlayer(), () => SelectedPlayer != null);
}
public ICommand DeletePlayerCommand
{
get { return _deletePlayerCommand; }
}
public Player SelectedPlayer
{
get { return _selectedPlayer; }
set
{
SetProperty(ref _selectedPlayer, value);
OnPropertyChanged(() => FormattedPlayerStatus);
_deletePlayerCommand.RaiseCanExecuteChanged();
}
}
}
Upvotes: 5