2010-03-15 29 views
19

Tôi đang mã hóa một UserControl đăng nhập đơn giản với hai TextBoxes (Tên người dùng và Mật khẩu) và nút Đăng nhập. Tôi muốn nút Login chỉ được kích hoạt khi các trường username và password được điền vào. Tôi đang sử dụng Prism và MVVM. LoginViewModel chứa một thuộc tính được gọi là LoginCommand được gắn kết với nút Login. Tôi có một phương thức CanLoginExecute() trong ViewModel nhưng nó chỉ kích hoạt khi ứng dụng xuất hiện và sau đó không bao giờ trở lại. Vì vậy, nút Đăng nhập không bao giờ được bật. Tôi đang thiếu gì?WPF-Prism Phương thức CanExecute không được gọi là

Dưới đây là XAML của tôi:

<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}" /> 

Dưới đây là ViewModel của tôi

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 
} 
+0

CMND là gì: Click.Command =, nó là một cái gì đó Prism cụ thể. Tôi thường làm

+0

Có, cmnd: Click.Command = là lăng kính cụ thể: xmlns: cmnd = "clr-namespace: Microsoft.Practices.Composite.Presentation.Commands; assembly = Microsoft.Practices.Composite.Presentation" Vì tôi đang sử dụng Prism's DelegateCommand, tôi nghĩ đây sẽ là cơ chế ràng buộc lệnh tương thích. Tôi cũng đã thử Command = "{Binding LoginCommand}" - nó hoạt động chính xác như nhau. – Naresh

Trả lời

40

Có khả năng nhất mà sự kiểm soát ràng buộc là không bao giờ yêu cầu trạng thái CanExecute một lần nữa. Bạn cần gọi phương thức RaiseCanExecuteChanged trên DelegateCommand bất cứ khi nào bạn phát hiện điều kiện thay đổi trạng thái Trạng thái CanExecute của lệnh. Điều này báo hiệu kiểm soát bị ràng buộc để cập nhật trạng thái CanExecute.

+0

RaiseCanExecuteChanged hoạt động như một sự quyến rũ! Cảm ơn olli – Naresh

+18

Chỉ cần cho các hồ sơ (điều này đã xảy ra với tôi), tôi đã không tìm thấy phương pháp 'RaiseCanExecuteChanged' bởi vì tôi đã sử dụng giao diện ICommand. Phương thức này được định nghĩa trong triển khai DelegateCommand, vì vậy tôi cần phải đúc nó. – alf

8

Mã cho RaiseCanExecuteChanged:

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(); 
     } 
    } 
Các vấn đề liên quan