为什么不能';t我的命令启用按钮
本文关键字:我的 命令 启用 按钮 不能 为什么 | 更新日期: 2023-09-27 18:20:54
我正在学习使用Prism中的DelgateCommand。。。。
在我的UI中,我有我的用户名文本框和密码框:
<TextBox Name="_UserNameTextBox" Text="{Binding UserName, Mode=TwoWay}" />
<PasswordBox Name="_PasswordBox"></PasswordBox>
还有我的登录按钮:
<Button Name="button1" Command="{Binding LoginCommand, Mode=TwoWay}" CommandTarget="{Binding ElementName=_UserNameTextBox, Path=Text}">Login</Button>
然后我的ViewModel我有:
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;
}
);
}
我可以看到我的UserName绑定正确,并且我确实在ViewModel构造函数中传递了我的PasswordBox作为引用。当我执行应用程序时,按钮被禁用,所以我知道它绑定到了命令上。
但我从来没有看到我写的CanExecute delgate在我输入UserName和PasswordBox后被检查。。。。并且从未启用。。。
那么我做错了什么?
编辑:
=====
所以最终结果是…这个?
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;
}
);
}
一般来说,只要CanExecute
返回的影响值发生变化,就必须调用RaiseCanExecuteChanged
。在这种特定情况下,每当用户或密码字段的值发生更改时,您都需要调用它。但这非常困难,因为您的ViewModel实现是完全错误的。
以下是您应该做的:
- 在ViewModel中公开
Username
和Password
属性。您需要显式地实现getter和setter(即它不能是一个自动属性) - 在视图中,将用户名和密码输入字段的内容绑定到这些属性
- 在属性设置器中,调用
LoginCommand.RaiseCanExecuteChanged
以下是当你这样做时会发生的事情(让我们选择密码框作为示例):
- 用户在密码框中键入一个字符
- 由于双向绑定,WPF设置
LoginViewModel.Password
的值 - 密码设置程序调用
RaiseCanExecuteChanged
,这将在您的命令中引发CanExecuteChanged
事件 - 提交按钮(当您将其绑定到命令时,它已经订阅了该事件)会收到通知
- 该按钮调用
CanExecute
以查看现在是否允许执行该命令 - 您的代理运行并返回
true
,因此按钮会自行激活
您需要绑定Button.CommandParameter
(它将被传递给Execute
和CanExecute
),如果该绑定发生更改,则据我所知,CanExecute
将被重新赋值。
(我认为您混淆了CommandParameter
和CommandTarget
,CommandTarget
不在命令中使用,它只用于在某个元素上引发命令(这可能与命令路由等相关)