5

次のような登録ページにMVVMパターンを実装したいと思います。

ページには、ユーザー名、電子メール、およびパスワード用のテキストボックスがあります。

ICommandおよびDelegateCommandパターンを使用して、登録ボタンをコマンドにバインドしたいと思います。

問題は、テキストボックスが空の場合はボタンを無効にし、テキストがある場合はボタンを有効にすることです。

私のモデルは:

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

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

私のDelegateCommand実装:

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

        }



    }

と私の見解

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

私が達成したいのは、ユーザーが各テキストボックスに情報を入力するまでボタンを無効にすることです

これはどのように行うことができますか?

ありがとう

4

1 に答える 1

7

DelegateCommandまず最初に、プロパティにアクセスするたびにnewを返すRaiseCanExecuteChanged()と、バインドされているのと同じコマンドへの参照がないため、メソッドを呼び出す機能が制限されます。

したがって、ViewModelを次のように変更します。

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

バインディングが発生する前にインスタンス化され、変更する必要がないため、PropertyChanged呼び出しなしでRegisterCommandプロパティを使用できる理由。private set

プロパティの形式を想定してイベントUserNamePasswordトリガーすると、プロパティが変更されたときにメソッドをPropertyChanged呼び出すことができます。RaiseCanExecuteChanged()RegisterCommand

例えば。

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

        _userName = value;
        RaisePropertyChanged("UserName");

        RegisterCommand.RaiseCanExecuteChanged();
    }
}

これにより、CanExecuteメソッドが強制的に再評価されます。

于 2013-01-20T23:49:58.557 に答える