2013-01-20 17 views
5

Voglio realizzare MVVM picchiettio ad una pagina registeration come questo:Windows Phone MVVM: Pulsante di comando può Esegui e Command Paramtere

la pagina ha caselle di testo per nome utente, email e password.

voglio legare il pulsante Registra per un comando utilizzando ICommand e DelegateCommand modello.

Il problema è che voglio che il pulsante sia disabilitato se le caselle di testo sono vuote e abilitate se hanno un testo.

mio Modello è:

public class User 
    { 
     public string UserName { get; set; } 
     public string Email { get; set; } 
     public string Password { get; set; } 
    } 

mio ViewModel:

public class UserViewModel:INotifyPropertyChanged 
    { 
     private User user; 
     public UserViewModel() 
     { 
      user = new User(); 
     } 
#region Properties 
. 
. 
. 
#endregion 
public ICommand RegisterCommand 
     { 
      get 
      { 
       return new DelegateCommand(Register,CanRegister); 
      } 
     } 

     private void Register(object parameter) 
     { 
      //TODO call the web service 
     } 

     private bool CanRegister(object parameter) 
     { 
      return (!string.IsNullOrEmpty(UserName) && !string.IsNullOrEmpty(Password)); 
     } 
} 

mio DelegateCommand Implementazione:

public class DelegateCommand:ICommand 
    { 
     //Delegate to the action that the command executes 
     private Action<object> _executeAction; 
     //Delegate to the function that check if the command can be executed or not 
     private Func<object, bool> _canExecute; 

     public bool canExecuteCache; 

     public DelegateCommand(Action<object> executeAction):this(executeAction,null) 
     { 

     } 

     public DelegateCommand(Action<object> action, Func<object, bool> canExecute) 
     { 
      this._executeAction = action; 
      this._canExecute = canExecute; 
     } 

     //interface method, called when CanExecuteChanged event handler is fired 
     public bool CanExecute(object parameter) 
     { 
      //true by default (in case _canExecute is null) 
      bool result = true; 
      Func<object, bool> canExecuteHandler = this._canExecute; 
      if (canExecuteHandler != null) 
      { 
       result = canExecuteHandler(parameter); 
      } 

      return result; 
     } 

     //Event handler that the controld subscribe to 
     public event EventHandler CanExecuteChanged; 


     //interface method 
     public void Execute(object parameter) 
     { 
      _executeAction(parameter); 
     } 


     //rause the CanExecuteChanged event handler manually 
     public void RaiseCanExecuteChanged() 
     { 
      EventHandler handler = this.CanExecuteChanged; 
      if (handler != null) 
      { 
       handler(this, EventArgs.Empty); 
      } 

     } 



    } 

e mio Vista:

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> 
      <Grid.RowDefinitions> 
       <RowDefinition Height="Auto"/> 
       <RowDefinition Height="Auto"/> 
       <RowDefinition Height="Auto"/> 
       <RowDefinition Height="Auto"/> 
       <RowDefinition Height="Auto"/> 
      </Grid.RowDefinitions> 
      <TextBlock Grid.Row="0" Text="Username:"/> 
      <TextBox Grid.Row="1" Name="txtUserName" Text="{Binding UserName, Mode=TwoWay}" HorizontalAlignment="Stretch"/> 
      <TextBlock Grid.Row="2" Text="Password:" HorizontalAlignment="Stretch" /> 
      <TextBox Grid.Row="3" Name="txtPassword" Text="{Binding Password, Mode=TwoWay}"/> 
      <Button Grid.Row="4" Content="Register" Command="{Binding RegisterCommand }" /> 
     </Grid> 

Quello che voglio raggiungere è quello di rendere il pulsante disattivato fino a che l'utente inserisce informazioni in ogni TextBox

come può essere fatto?

Grazie

risposta

7

Una cosa prima: Restituzione di una nuova DelegateCommand ogni volta che la proprietà si accede limiterà la vostra capacità di chiamare il metodo RaiseCanExecuteChanged() come non sarà necessario un riferimento alla stesso comando è destinato.

Quindi modificare il ViewModel per essere qualcosa di simile:

public class UserViewModel : INotifyPropertyChanged 
{ 
    private User user; 
    public UserViewModel() 
    { 
     user = new User(); 
     RegisterCommand = new DelegateCommand(Register,CanRegister); 
    } 

    public DelegateCommand RegisterCommand {get; private set;} 

    private void Register(object parameter) 
    { 
     //TODO call the web service 
    } 

    private bool CanRegister(object parameter) 
    { 
     return (!string.IsNullOrEmpty(UserName) && 
       !string.IsNullOrEmpty(Password)); 
    } 
} 

La ragione per cui si può avere la proprietà RegisterCommand come private set con nessuna chiamata PropertyChanged come sarà un'istanza prima che avvenga la vincolante e non ha bisogno di modificare.

assumendo la forma di proprietà UserName e Password attivare l'evento PropertyChanged, si può chiamare il metodo RaiseCanExecuteChanged() sul RegisterCommand quando cambiano.

Es.

private string _userName; 
public string UserName 
{ 
    get { return _userName; } 
    set 
    { 
     if(_userName == value) 
      return; 

     _userName = value; 
     RaisePropertyChanged("UserName"); 

     RegisterCommand.RaiseCanExecuteChanged(); 
    } 
} 

questo forzerà il riesame del metodo CanExecute.

+0

Grazie mille, mi hai salvato la giornata :) –

+0

@MinaSamy Il mio piacere :) –