2013-01-20 14 views
5

Tôi muốn thực hiện MVVM patter đến một trang Registeration như thế này:Windows Phone MVVM: Nút lệnh có thể thực hiện và Command Paramtere

Trang có hộp văn bản cho tên người dùng, email và mật khẩu.

Tôi muốn gắn nút Đăng ký vào lệnh bằng cách sử dụng ICommandMẫu DelegateCommand.

Vấn đề là tôi muốn nút bị tắt nếu hộp văn bản trống và được bật nếu chúng có văn bản.

My Mẫu là:

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

My 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 Thực hiện:

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

     } 



    } 

và My Xem:

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

Những gì tôi muốn đạt được là làm cho nút vô hiệu hóa cho đến khi người dùng nhập vào thông tin trong mỗi TextBox

thế nào điều này có thể được thực hiện?

Cảm ơn

Trả lời

7

Một điều đầu tiên: Trả về một mới DelegateCommand mỗi khi tài sản được truy cập sẽ hạn chế khả năng của bạn để gọi phương thức RaiseCanExecuteChanged() vì bạn sẽ không có một tham chiếu đến cùng một lệnh như là bị ràng buộc.

Vì vậy, thay đổi ViewModel của bạn để có một cái gì đó như thế này:

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

Lý do bạn có thể có tài sản như private setRegisterCommand không có cuộc gọi PropertyChanged vì nó sẽ được khởi tạo trước khi ràng buộc xảy ra và không cần phải thay đổi.

Giả dạng các thuộc tính UserNamePassword kích hoạt sự kiện PropertyChanged, bạn chỉ có thể gọi phương thức RaiseCanExecuteChanged() trên RegisterCommand khi họ thay đổi.

Ví dụ:

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

     _userName = value; 
     RaisePropertyChanged("UserName"); 

     RegisterCommand.RaiseCanExecuteChanged(); 
    } 
} 

điều này sẽ buộc phương pháp CanExecute được đánh giá lại.

+0

Cảm ơn rất nhiều, bạn đã lưu ngày của tôi :) –

+0

@MinaSamy Niềm vui của tôi :) –