【问题标题】:Enable button without exposing model properties启用按钮而不暴露模型属性
【发布时间】:2021-05-12 10:53:51
【问题描述】:

我正在使用带有MVVMHelpers 的 MVVM 模式。

我已经制作了登录表单,但我试图仅在用户输入了他的用户名和密码后才启用该按钮。

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

【问题讨论】:

    标签: c# wpf xaml mvvm


    【解决方案1】:

    可以仅在 XAML 中实现此目的,方法是在 登录Button 上的 IsEnabled 属性上使用多重绑定到用户名和密码TextBoxes 以及一个自定义值转换器,将绑定的strings 转换为指示它们是否为空的bool

    但是,在这种情况下这是不可能的,因为您应该避免同时使用CommandIsEnabled,因为这会导致奇怪的行为。命令提供了一种机制来确定一个动作是否可能和will in turn set the IsEnabled state

    一个命令可以通过实现 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,则在返回@时将自动启用或禁用绑定该命令的控件987654339@。使用这种方法,您根本不需要 IsEnabled 属性,您可以从 XAML 中删除它

    这里唯一要注意的另一件事是,当它需要通过调用RaiseCanExecuteChanged 方法(在Command 类中定义)来重新评估CanExecute 委托时,您必须告诉LoginCommand。为了访问它,将属性的类型从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}" />
    

    【讨论】:

    • 谢谢我做到了,但我还有另一个问题
    猜你喜欢
    • 1970-01-01
    • 2015-08-08
    • 2012-03-29
    • 1970-01-01
    • 1970-01-01
    • 2014-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多