2010-03-15 8 views
19

Je code un UserControl de connexion simple avec deux TextBox (nom d'utilisateur et mot de passe) et un bouton de connexion. Je veux que le bouton de connexion soit activé seulement quand les champs de nom d'utilisateur et de mot de passe sont remplis. J'utilise Prism et MVVM. Le LoginViewModel contient une propriété appelée LoginCommand qui est liée au bouton de connexion. J'ai une méthode CanLoginExecute() dans mon ViewModel mais elle ne se déclenche que lorsque l'application arrive et plus jamais. Le bouton de connexion n'est donc jamais activé. Qu'est-ce que je rate?Méthode WPF-Prism CanExecute non appelée

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

Voici mon 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

Quelle est cmnd: Click.Command =, est-il quelque chose de spécifique Prism. Je fais habituellement

+0

Oui, cmnd: Click.Command = est spécifique prisme: xmlns: cmnd = "clr-namespace: Microsoft.Practices.Composite.Presentation.Commands; assemblage = Microsoft.Practices.Composite.Presentation" Depuis que je suis en utilisant Je pensais que le DelegateCommand de Prism serait le mécanisme de liaison de commande compatible. J'ai aussi essayé directement Command = "{Binding LoginCommand}" - cela fonctionne exactement de la même manière. – Naresh

Répondre

40

Il est fort probable que le contrôle lié est ne demande le nouveau état CanExecute. Vous devez appeler la méthode RaiseCanExecuteChanged sur DelegateCommand chaque fois que vous détectez une condition qui modifie l'état CanExecute de la commande. Cela signale au contrôle lié de mettre à jour l'état CanExecute.

+0

RaiseCanExecuteChanged fonctionne comme un charme! Merci olli – Naresh

+18

Juste pour l'enregistrement (cela m'arrivait), je ne trouvais pas la méthode 'RaiseCanExecuteChanged' parce que j'utilisais l'interface ICommand. Cette méthode est définie dans l'implémentation DelegateCommand, j'ai donc dû la convertir. – alf

8

Code pour 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(); 
     } 
    } 
Questions connexes