2010-03-15 10 views
19

jestem kodowania prostego logowania UserControl z dwóch pól tekstowych (nazwa użytkownika i hasło) i przycisku logowania. Chcę, aby przycisk logowania był włączony tylko wtedy, gdy pola nazwy użytkownika i hasła są wypełnione. Używam Prism i MVVM. LoginViewModel zawiera właściwość o nazwie LoginCommand, która jest przypisana do przycisku Login. Mam metodę CanLoginExecute() w moim ViewModel, ale uruchamia się tylko wtedy, gdy aplikacja pojawia się, a następnie nigdy więcej. Tak więc przycisk logowania nigdy nie jest włączony. czego mi brakuje?metoda WPF Prism CanExecute nie miano

Oto mój 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}" /> 

Oto mój 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 
} 
+0

Co jest POLEC: Click.Command =, jest to coś Prism specyficzny. Zwykle robię

+0

Tak, POLEC: Click.Command = pryzmat jest specyficzny: xmlns: POLEC = "clr-namespace: Microsoft.Practices.Composite.Presentation.Commands; montaż = Microsoft.Practices.Composite.Presentation" Ponieważ używam Prism's DelegateCommand, myślałem, że będzie to kompatybilny mechanizm wiążący polecenia. Próbowałem również polecenia Command = "{Binding LoginCommand}" - działa dokładnie tak samo. – Naresh

Odpowiedz

40

Jest bardzo prawdopodobne, że kontrola związana nie prosi o stanie CanExecute ponownie. Musisz zadzwonić do RaiseCanExecuteChanged sposób na DelegateCommand kiedy tylko wykryje stan, który zmienia CanExecute stan danego polecenia. sygnalizuje ten związanego kontrolę w celu zaktualizowania CanExecute stan.

+0

RaiseCanExecuteChanged działa jak urok! Dzięki olli – Naresh

+18

Tylko dla rekordu (tak mi się działo), nie znalazłem metody "RaiseCanExecuteChanged", ponieważ korzystałem z interfejsu ICommand. Ta metoda jest zdefiniowana w implementacji DelegateCommand, więc musiałem ją rzucić. – alf

8

Kod 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(); 
     } 
    }