I am learning to use DelgateCommand from Prism….
In my UI, I have my UserName textbox and PasswordBox:
<TextBox Name="_UserNameTextBox" Text="{Binding UserName, Mode=TwoWay}" />
<PasswordBox Name="_PasswordBox"></PasswordBox>
And my Login Button:
<Button Name="button1" Command="{Binding LoginCommand, Mode=TwoWay}" CommandTarget="{Binding ElementName=_UserNameTextBox, Path=Text}">Login</Button>
Then my ViewModel I have:
string _UserName = string.Empty;
public string UserName
{
get
{
return _UserName;
}
set
{
if (value != _UserName)
{
_UserName = value;
RaisePropertyChanged("UserName");
}
}
}
//For reference the password
PasswordBox _PasswordBox { get; set; }
public DelegateCommand<string> LoginCommand { get; set; }
public LoginViewModel(PasswordBox passwordBox)
{
_PasswordBox = passwordBox;
LoginCommand = new DelegateCommand<string>(
(
//Execute
(str) =>
{
Login(_PasswordBox.Password);
}
),
//CanExecute Delgate
(usr) =>
{
if (string.IsNullOrEmpty(usr) || string.IsNullOrEmpty(_PasswordBox.Password))
return false;
return true;
}
);
}
I can see my UserName is binding properly and I did pass my PasswordBox as referece in ViewModel constructor. When I execute the application the Button is disabled, so I know is binded to the command.
But I never see the CanExecute delgate that I wrote is being check after I type things in UserName and PasswordBox…. And is never enabled…
So what did I done wrong?
EDIT:
=====
So end result is…this?
string _UserName = string.Empty;
public string UserName
{
get
{
return _UserName;
}
set
{
if (value != _UserName)
{
_UserName = value;
RaisePropertyChanged("UserName");
LoginCommand.RaiseCanExecuteChanged();
}
}
}
//For reference the password
PasswordBox _PasswordBox { get; set; }
public DelegateCommand<string> LoginCommand { get; set; }
public LoginViewModel(PasswordBox passwordBox)
{
_PasswordBox = passwordBox;
_PasswordBox.PasswordChanged += delegate(object sender, System.Windows.RoutedEventArgs e)
{
LoginCommand.RaiseCanExecuteChanged();
};
LoginCommand = new DelegateCommand<string>(
(
(str) =>
{
Login(_PasswordBox.Password);
}
),
(usr) =>
{
if (string.IsNullOrEmpty(usr) || string.IsNullOrEmpty(_PasswordBox.Password))
return false;
return true;
}
);
}
Generally speaking, you have to call
RaiseCanExecuteChangedwhenever the effecting value returned byCanExecutechanges. In this specific case you would need to call it whenever the value of the user or password fields changes. But that is exceedingly difficult, because your ViewModel implementation is totally wrong.Here’s what you should do instead:
Usernameand aPasswordproperty inside your ViewModel. You will need to implement the getters and setters explicitly (i.e. it cannot be an automatic property).LoginCommand.RaiseCanExecuteChanged.Here’s what will happen when you do this (let’s pick the password box for an example):
LoginViewModel.Passwordbecause of the two-way binding.RaiseCanExecuteChanged, which raises theCanExecuteChangedevent on your command.CanExecuteto see if executing the command is now allowed.true, so the button activates itself.