Reputation: 383
I'm learning Mvvmlight,and quite confused about its canExecute
of RelayCommand.
Basically,I have a Button
and a PasswordBox
in the view
,and a Command
in the viewModel
.What I want is to disable the Button if the PasswordBox is empty.My solution is to pass the PasswordBox as CommandParemeter to the Button,then receive the PasswordBox in the canExecute method and specify if it is null or empty.I first declare a command:
public ICommand CommandClear { get; private set; }
Then instantialize it in the Class Constructor
:
CommandConfirm = new RelayCommand<object>((p) => ConfirmExecute(p), (p) => ConfirmCanExecute(p));
Finally implement the canExecute
method as below:
private bool ConfirmCanExecute(object parameter)
{
bool isExecuable = false;
var passwordBox = parameter as PasswordBox;
if (!string.IsNullOrEmpty(passwordBox.Password))
isExecuable = true;
return isExecuable;
}
The canExecute method above does not work,as an unhandled exception System.Reflection.TargetInvocationException
would be thrown in PresentationFramework.dll
.
So I try to wrap the code above with try...catch
.This time,it works like magic:
try
{
var passwordBox = parameter as PasswordBox;
if (!string.IsNullOrEmpty(passwordBox.Password))
isExecuable = true;
return isExecuable;
}
catch
{
return isExecuable;
}
I'm quite confused about such behavior of canExecute
,any ideas?
Upvotes: 2
Views: 1201
Reputation:
Are you declaring p on the stack in this line and does it still exist when the handler is called?
CommandConfirm = new RelayCommand<object>((p) => ConfirmExecute(p), (p) => ConfirmCanExecute(p));
Because an incorrect command binding would certainly cause this to return null, creating the error you're seeing.
var passwordBox = parameter as PasswordBox;
Secondly, why have your ViewModel directly manipulate the View in this way? Simply 2-way bind the Password field to your ViewModel and your ViewModel's CanExecute handler becomes a one-liner, no?
return !String.IsNullOrEmpty(this.Password);
Upvotes: 3