启用按钮而不公开模型属性



我将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中实现这一点,方法是在登录ButtonIsEnabled属性上使用与用户名和密码TextBoxes的多重绑定,以及将绑定的strings转换为指示它们是否为空的bool的自定义值转换器。

然而,在这种情况下,这是不可能的,因为您应该避免同时使用CommandIsEnabled,因为这可能会导致奇怪的行为。命令提供了一种机制来确定操作是否可行,并将依次设置IsEnabled状态。

命令可以通过实现CanExecute方法来指示操作是否可行。按钮可以订阅CanExecuteChanged事件,如果CanExecute返回false则禁用按钮,如果CanExecute返回true则启用按钮。

如您所见,同时设置CommandIsEnabled会相互干扰。虽然它可能会起作用,但如果在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,或为其定义一个单独的支持字段。在这种情况下,每次UsernamePassword更改时都需要重新评估它,因此请将它放在它们的setter中。

目前,用户名和密码的TextBoxes仅在失去焦点时(例如,在其外部或其他控件上单击(才更新视图模型属性。如果希望登录按钮对每次击键作出反应,请将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}" />

最新更新