代码之家  ›  专栏  ›  技术社区  ›  Naresh

未调用WPF Prism CanExecute方法

  •  20
  • Naresh  · 技术社区  · 16 年前

    我用两个文本框(用户名和密码)和一个登录按钮编写了一个简单的登录用户控件。我希望登录按钮只在用户名和密码字段填写时启用。我正在使用Prism和MVVM。LoginViewModel包含一个名为LoginCommand的属性,该属性绑定到Login按钮。我在ViewModel中有一个CanLoginExecute()方法,但它只在应用程序启动时触发,然后再也不会触发。因此,登录按钮从未启用。我错过了什么?

    这是我的xaml:

    <TextBox x:Name="username"
        Text="{Binding Path=Username, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
    <TextBox x:Name="password"
        Text="{Binding Path=Password, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
    <Button Content="Login"
        cmnd:Click.Command="{Binding LoginCommand}" />
    

    这是我的ViewModel

    class LoginViewModel : IDataErrorInfo, INotifyPropertyChanged
    {
        public LoginViewModel()
        {
            this.LoginCommand =
                new DelegateCommand<object>(
                    this.LoginExecute, this.CanLoginExecute);
        }
    
        private Boolean CanLoginExecute(object dummyObject)
        {
            return (string.IsNullOrEmpty(Username) ||
                    string.IsNullOrEmpty(Password)) ? false : true;
        }
    
        private void LoginExecute(object dummyObject)
        {
            if (CheckCredentials(Username, Password))
            {
                ....
            }
        }
    
        #region IDataErrorInfo Members
    
        public string Error
        {
            get { throw new NotImplementedException(); }
        }
    
        public string this[string columnName]
        {
            get
            {
                string result = null;
                if (columnName == "Username")
                {
                    if (string.IsNullOrEmpty(Username))
                        result = "Please enter a username";
                }
                else if (columnName == "Password")
                {
                    if (string.IsNullOrEmpty(Password))
                        result = "Please enter a password";
                }
                return result;
            }
        }
    
        #endregion // IDataErrorInfo Members
    
        #region INotifyPropertyChanged Members
    
        public event PropertyChangedEventHandler PropertyChanged;
    
        void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    
        #endregion // INotifyPropertyChanged Members
    
        #region Properties
    
        private String _username;
        public String Username
        {
            get { return _username; }
            set
            {
                if (value == _username)
                    return;
                _username = value;
                this.OnPropertyChanged("Username");
            }
        }
    
        private String _password;
        public String Password
        {
            get { return _password; }
            set
            {
                if (value == _password)
                    return;
                _password = value;
                this.OnPropertyChanged("Password");
            }
        }
    
        public ICommand LoginCommand { get; private set; }
    
        #endregion // Properties
    }
    
    4 回复  |  直到 16 年前
        1
  •  45
  •   olli-MSFT    16 年前

    很可能绑定控件从未要求 CanExecute公司 再说一遍。你得打电话给警察 提升Nexecutechanged CanExecute公司 CanExecute公司 州。

        2
  •  8
  •   Naresh    16 年前

        private void RaiseCanExecuteChanged()
        {
            DelegateCommand<object> command = LoginCommand as DelegateCommand<object>;
            command.RaiseCanExecuteChanged();
        }
    
        public const string UsernameProperty = "Username";
        private String _username;
        public String Username
        {
            get { return _username; }
            set
            {
                _username = value;
                this.NotifyPropertyChanged(UsernameProperty);
                RaiseCanExecuteChanged();
            }
        }
    
        3
  •  8
  •   VRage    8 年前

    从Prism6开始 DelegateCommand RaiseCanExecuteChanged 在楼房里。如果要观察更多属性,也可以链调用该方法:

    public LoginViewModel()
    {
        this.LoginCommand =
            new DelegateCommand<object>(
                this.LoginExecute, this.CanLoginExecute).ObservesProperty(() => Username).ObservesProperty(() => Password);
    }
    

    此外,如果只是希望根据布尔属性的状态调用DelegateCommand,则可以使用 .ObservesCanExecute(()=> BoolProp)

    public LoginViewModel()
    {
        this.LoginCommand =
            new DelegateCommand<object>(
                this.LoginExecute).ObservesCanExecute(()=> IsServerOnline).ObservesProperty(() => Username).ObservesProperty(() => Password);
    }
    

    你不需要 this.CanLoginExecute 不再

        4
  •  2
  •   Glutwolf    7 年前

    下面是Prism的一个小解决方法(使用Prism.Core 7.1.0.431进行了测试):

    public class RelayCommand : DelegateCommand
    {
        public RelayCommand(Action executeMethode) : base(executeMethode)
        {
    
        }
    
        public RelayCommand(Action executeMethode, Func<bool> canExecuteMethode) : base(executeMethode, canExecuteMethode)
        {
    
        }
    
        public override event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }
    }