Как отключить кнопку OK диалога WPF в ответ на неверный ввод, определенный пользовательским классом ValidationRule? - PullRequest
1 голос
/ 24 января 2011

У меня есть простой диалог WPF, позволяющий пользователю вводить имя.Мы используем подход Mvvm без каких-либо файлов с выделенным кодом.Мне нужно подтвердить ввод и включить кнопку ОК только тогда, когда ввод действителен.В настоящее время я выполняю проверку с использованием настраиваемого шаблона ошибок в моем представлении и пользовательской реализации класса ValidationRule.

Текстовое поле в диалоге определяется как:

    <TextBox Width="250" Height="25" Margin="5"
             Validation.ErrorTemplate="{StaticResource customErrorTemplate}">
        <TextBox.Text>
            <Binding Path="WitnessName" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged">
                <Binding.ValidationRules>
                    <ValidationRules:NameRule />
                </Binding.ValidationRules>
            </Binding>
        </TextBox.Text>
    </TextBox>

NameRuleопределяется как:

public class NameRule : ValidationRule
{
    public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
    {
        var isValid = (value as string == null) || Regex.IsMatch(value.ToString(), @"^[\p{L} \.'\-]+$");

        return new ValidationResult(isValid, "Name can contain only letters, apostrophes and hyphens.");
    }
}

Свойство IsEnabled кнопки OK привязано к свойству IsOkEnabled в модели представления, которое имеет значение true, только если вход является действительным.

<Button Name="OnOkClick" Margin="5" IsEnabled="{Binding IsOkEnabled}">OK</Button>

IsOkEnabledсвойство обновляется в ответ на изменение в тексте WitnessName путем мониторинга события PropertyChanged WitnessName.

public string WitnessName
{
    get
    {
        return this.witnessName;
    }

    set
    {
        this.witnessName = value;
        this.NotifyOfPropertyChange(() => this.IsOkEnabled);
    }
}

Проблема заключается в том, что при проверке, работающей в представлении, событие PropertyChanged не запускается в vewмодели при вводе недопустимого ввода, поэтому свойство IsOkEnabled не обновляется и кнопка «ОК» остается включенной.

Существует ли способ принудительного обновления свойства IsOkEnabled в ответ на даже недопустимый ввод на моемтекущая реализация?

Я смотрел на оба Карла Шифлета и Джоша Смита , но ни один из них не использует (насколько я могу судить) шаблон ошибки просмотра, и я хотел бы использовать его для визуальной обратной связи.

Обновление: пробуя это со связанной ICommand, как предложено Danny

Я попробовал это, создав виртуальную машину, специфичную для кнопки OK, которая реализует ICommand.OkButtonViewModel имеет свойство для хранения виртуальной машины диалога (устанавливается IoC и unity), а реализации CanExecute и Execute ссылаются на соответствующие свойства / методы на этой виртуальной машине.

В OkButtonViewModel:

public bool CanExecute(object parameter)
{
    return this.witnessDialogue.IsValid;
}

public void Execute(object parameter)
{
    this.witnessDialogue.OnOkClick();
}

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

Ответы [ 2 ]

1 голос
/ 24 января 2011

Избавьтесь от обработчика событий OnClick, вместо этого используйте привязку к команде.Зарегистрируйте команду в виртуальной машине с помощью метода CanExecute, который возвращает Model.IsValid.

Если ошибка проверки связана с привязкой представления к модели представления, тогда модель представления все еще может быть действительной, поскольку она несохранить обновление (из-за несоответствия типов, проверки диапазона и т. д.).

В этом случае рассмотрите возможность сохранения состояния ошибки в виртуальной машине перед выдачей исключения, а затем очистите состояние ошибки, если это свойство было успешно установлено.1006 * Модифицированный код:

XAML: (Обратите внимание, что область действия экземпляра ValidationRules: NameRule находится в TextBox, другие пользователи получат другой экземпляр с другими значениями полей)

<TextBox Width="250" Height="25" Margin="5"
         Validation.ErrorTemplate="{StaticResource customErrorTemplate}">
    <TextBox.Text>
        <Binding Path="WitnessName" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged">
            <Binding.ValidationRules>
                <ValidationRules:NameRule x:Name="nameValidator" />
            </Binding.ValidationRules>
        </Binding>
    </TextBox.Text>
</TextBox>

Правило валидации:

public class NameRule : ValidationRule, INotifyPropertyChanged
{
   public bool HasFailed // set default of field behind to false
   {
      get; // change to support INotifyPropertyChanged
      set; // change to support INotifyPropertyChanged
   }

    public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
    {
        var isValid = (value as string == null) || Regex.IsMatch(value.ToString(), @"^[\p{L} \.'\-]+$");

        HasFailed = !isValid;

        return new ValidationResult(isValid, "Name can contain only letters, apostrophes and hyphens.");
    }
}

Команда:

public bool CanExecute(object parameter)
{
    return this.witnessDialogue.IsValid && !this.witnessDialogue.nameValidator.HasFailed;
}

public void Execute(object parameter)
{
    this.witnessDialogue.OnOkClick();
}
0 голосов
/ 17 декабря 2018

Я знаю, что это действительно старый вопрос, но для тех, кто руководит здесь Google, как я был ...

Лучший способ (который я знаю) сделать это в WPF с MVVM -используйте интерфейс IDataErrorInfo в вашей модели представления, где находится определение команды.Это позволяет вам проверять и иметь информацию проверки в вашей модели представления для работы с вашей реализацией CanExecute.Я нашел хорошее подробное описание использования этого в https://codeblitz.wordpress.com/2009/05/08/wpf-validation-made-easy-with-idataerrorinfo/ (не написал это, просто полезная ссылка, которую я нашел).

Надеюсь, это кому-нибудь поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...