2013-01-20 7 views
5

Chcę zaimplementować MVVM tupot do strony registeration tak:Windows Phone MVVM: Przycisk polecenia mogą wykonywać i poleceń Paramtere

strony ma pola tekstowe o nazwę użytkownika, adres e-mail i hasło.

Chcę powiązać przycisk Zarejestruj na polecenie używając ICommand i DelegateCommand wzór.

Problem polega na tym, że chcę, aby przycisk był wyłączony, jeśli pola tekstowe są puste i włączone, jeśli mają tekst.

Moja model jest:

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

Moja 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)); 
     } 
} 

My DelegateCommand realizacji:

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

     } 



    } 

i mój Zobacz:

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

Co chcę osiągnąć jest, aby przycisk wyłączone aż użytkownik wprowadzi informacje w każdej TextBox

jaki sposób można to zrobić?

Dzięki

Odpowiedz

7

Jedno pierwszy: Wracając nowy DelegateCommand każdym razem, gdy nieruchomość jest dostępne ograniczy zdolność do wywołania metody RaiseCanExecuteChanged() jak nie będą miały odniesienie do tego samego polecenia, jak jest związany.

Więc zmienić ViewModel być coś takiego:

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

Powodem można mieć właściwość RegisterCommand jako private set bez PropertyChanged rozmowy, jak to będzie instancja przed wiązania występuje i nie musi zmiana.

Zakładając formę własności UserName i Password wyzwalania zdarzeń PropertyChanged, wystarczy wywołać metodę RaiseCanExecuteChanged() na RegisterCommand gdy zmieni.

Np.

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

     _userName = value; 
     RaisePropertyChanged("UserName"); 

     RegisterCommand.RaiseCanExecuteChanged(); 
    } 
} 

to zmusi metodę CanExecute do ponownej oceny.

+0

Wielkie dzięki, uratowałeś mój dzień :) –

+0

@MinaSamy Moja przyjemność :) –