Почему моя команда не может включить кнопку? - PullRequest
0 голосов
/ 19 января 2012

Я учусь использовать DelgateCommand от Prism ....

В моем пользовательском интерфейсе у меня есть текстовое поле UserName и PasswordBox:

<TextBox Name="_UserNameTextBox" Text="{Binding UserName, Mode=TwoWay}" />

<PasswordBox Name="_PasswordBox"></PasswordBox>

и кнопка входа в систему:

<Button Name="button1" Command="{Binding LoginCommand, Mode=TwoWay}" CommandTarget="{Binding ElementName=_UserNameTextBox, Path=Text}">Login</Button>

Тогда моя ViewModel у меня есть:

    string _UserName = string.Empty;
    public string UserName
    {
        get
        {
            return _UserName;
        }
        set
        {
            if (value != _UserName)
            {
                _UserName = value;
                RaisePropertyChanged("UserName");
            }
        }

    }

    //For reference the password
    PasswordBox _PasswordBox { get; set; }


    public DelegateCommand<string> LoginCommand { get; set; }

    public LoginViewModel(PasswordBox passwordBox)
    {
        _PasswordBox = passwordBox;

        LoginCommand = new DelegateCommand<string>(
            (
                //Execute
                (str) =>
                {
                    Login(_PasswordBox.Password);
                }
            ),
                //CanExecute Delgate
                (usr) =>
                {
                    if (string.IsNullOrEmpty(usr) || string.IsNullOrEmpty(_PasswordBox.Password))
                        return false;
                    return true;
                }
            );
    }

Я вижу, что мое имя пользователя привязывается правильно, и я передал свой PasswordBox как ссылку в конструкторе ViewModel.Когда я запускаю приложение, кнопка отключается, поэтому я знаю, что она привязана к команде.

Но я никогда не вижу, чтобы записанная мной учетная запись CanExecute проверялась после того, как я набираю вещи в UserName и PasswordBox .... И никогда не включается ...

Так, что я сделал не так??

РЕДАКТИРОВАТЬ:

=====

Таким образом, конечный результат ... это?

string _UserName = string.Empty;
        public string UserName
        {
            get
            {
                return _UserName;
            }
            set
            {
                if (value != _UserName)
                {
                    _UserName = value;
                    RaisePropertyChanged("UserName");
                    LoginCommand.RaiseCanExecuteChanged();
                }
            }

        }

        //For reference the password
        PasswordBox _PasswordBox { get; set; }


        public DelegateCommand<string> LoginCommand { get; set; }

        public LoginViewModel(PasswordBox passwordBox)
        {
            _PasswordBox = passwordBox;
            _PasswordBox.PasswordChanged += delegate(object sender, System.Windows.RoutedEventArgs e)
            {
                LoginCommand.RaiseCanExecuteChanged();
            };
            LoginCommand = new DelegateCommand<string>(
                (
                    (str) =>
                    {
                        Login(_PasswordBox.Password);
                    }
                ),
                    (usr) =>
                    {
                        if (string.IsNullOrEmpty(usr) || string.IsNullOrEmpty(_PasswordBox.Password))                        
                            return false;
                        return true;
                    }
                );
        }

Ответы [ 2 ]

2 голосов
/ 19 января 2012

Вообще говоря, вы должны вызывать RaiseCanExecuteChanged всякий раз, когда изменяется действующее значение, возвращаемое CanExecute. В этом конкретном случае вам нужно будет вызывать его всякий раз, когда изменяется значение поля пользователя или пароля. Но это чрезвычайно сложно, потому что ваша реализация ViewModel совершенно неверна.

Вот что вы должны сделать вместо этого:

  1. Предоставьте свойства Username и Password внутри вашей ViewModel. Вам нужно будет реализовать методы получения и установки явным образом (т. Е. Это не может быть автоматическим свойством).
  2. С вашей точки зрения, свяжите содержимое полей ввода имени пользователя и пароля с этими свойствами.
  3. В инсталляторах собственности звоните LoginCommand.RaiseCanExecuteChanged.

Вот что произойдет, когда вы сделаете это (давайте выберем поле пароля для примера):

  1. Пользователь вводит символ в поле пароля.
  2. WPF устанавливает значение LoginViewModel.Password из-за двусторонней привязки.
  3. Установщик пароля вызывает RaiseCanExecuteChanged, что вызывает событие CanExecuteChanged по вашей команде.
  4. Кнопка отправки (которая подписалась на это событие, когда вы связали ее с командой) получает уведомление.
  5. Кнопка вызывает CanExecute, чтобы узнать, разрешено ли выполнение команды.
  6. Ваш делегат запускается и возвращает true, поэтому кнопка активируется сама.
1 голос
/ 19 января 2012

Вам необходимо связать Button.CommandParameter (который будет передан Execute и CanExecute), если это изменение изменится, CanExecute будет переоценено, насколько я знаю.

(я думаю, вы путаете CommandParameter с CommandTarget, CommandTarget не используется внутри команды, он используется только для повышениякоманда для определенного элемента (которая может быть релевантной с точки зрения маршрутизации команд и т. д.)

...