我将MVVM模式与MVVMHelpers一起使用。
我已经制作了登录表单,但只有当用户输入了用户名和密码时,我才尝试启用该按钮。
public ICommand LoginCommand { get; set; }
private string _Username;
public string Username {
get { return _Username; }
set {
if (_Username != value) {
_Username = value;
RaisePropertyChanged();
Activate();
}
}
}
private string _Password;
public string Password {
get { return _Password; }
set {
if (_Password != value) {
_Password = value;
RaisePropertyChanged();
Activate();
}
}
}
private bool _IsEnabled;
public bool IsEnabled {
get { return _IsEnabled; }
set {
if (_IsEnabled != value) {
_IsEnabled = value;
RaisePropertyChanged();
}
}
}
public bool Activate() {
if (!string.IsNullOrEmpty(Username) && !string.IsNullOrEmpty(Password)) {
IsEnabled = true;
return true;
}
return false;
}
public LoginVM() {
LoginCommand = new Command(() => {
MessageBox.Show("LogeIn");
});
}
}
正如您所看到的,我通过向VM公开类的属性来实现这一点。我想知道是否有一种方法可以做到这一点而不暴露它?https://github.com/eduardoagr?tab=repositories
您可以仅在XAML中实现这一点,方法是在登录Button
的IsEnabled
属性上使用与用户名和密码TextBox
es的多重绑定,以及将绑定的string
s转换为指示它们是否为空的bool
的自定义值转换器。
然而,在这种情况下,这是不可能的,因为您应该避免同时使用Command
和IsEnabled
,因为这可能会导致奇怪的行为。命令提供了一种机制来确定操作是否可行,并将依次设置IsEnabled
状态。
命令可以通过实现CanExecute方法来指示操作是否可行。按钮可以订阅CanExecuteChanged事件,如果CanExecute返回false则禁用按钮,如果CanExecute返回true则启用按钮。
如您所见,同时设置Command
和IsEnabled
会相互干扰。虽然它可能会起作用,但如果在XAML中在Command
之前指定IsEnabled
,这是一个脆弱的解决方案,所以请选择一个,在这种情况下,更喜欢具有内置机制的Command
。
好消息是,您可以在视图模型中实现同样的效果,而不是在XAML中执行此操作,并通过将CanExecute
委托传递给LoginCommand
来节省一些代码,如下所示。
public class LoginVM : ViewModelBase {
public Command LoginCommand { get; }
private string _Username;
public string Username {
get { return _Username; }
set {
if (_Username != value) {
_Username = value;
RaisePropertyChanged();
LoginCommand.RaiseCanExecuteChanged();
}
}
}
private string _Password;
public string Password {
get { return _Password; }
set {
if (_Password != value) {
_Password = value;
RaisePropertyChanged();
LoginCommand.RaiseCanExecuteChanged();
}
}
}
public LoginVM() {
LoginCommand = new Command(
() => MessageBox.Show("Log IN"),
() => !string.IsNullOrEmpty(Username) && !string.IsNullOrEmpty(Password));
}
}
命令的第二个参数是一个方法,用于确定命令是否可以执行,如果返回true
,则在返回false
时,绑定该命令的控件将自动启用或禁用。使用这种方法,您根本不需要IsEnabled
属性,并且可以将其从XAML中删除。
这里唯一需要注意的是,当LoginCommand
需要通过调用其RaiseCanExecuteChanged
方法(在Command
类中定义(来重新评估CanExecute
委托时,您必须告诉它。为了访问它,请将属性的类型从ICommand
更改为Command
,或为其定义一个单独的支持字段。在这种情况下,每次Username
或Password
更改时都需要重新评估它,因此请将它放在它们的setter中。
目前,用户名和密码的TextBox
es仅在失去焦点时(例如,在其外部或其他控件上单击(才更新视图模型属性。如果希望登录按钮对每次击键作出反应,请将UpdateSourceTrigger
更改为PropertyChanged
。
<inputLayout:SfTextInputLayout x:Name="sfTextInputLayout"
Hint="Username"
Margin="20,20,20,0">
<TextBox Foreground="BlanchedAlmond"
Text="{Binding Username, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</inputLayout:SfTextInputLayout>
<controls:CustomPasswordBox Password="{Binding Password, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />