Как запустить проверку для одного свойства, когда другое свойство было проверено, используя пользовательские ValidationAttribute и INotifyDataErrorInfo

До недавнего времени я использовал расширенную версию IDataErrorInfo интерфейс. Мое расширение позволяет мне работать с несколькими ошибками одновременно, и пока оно мне очень хорошо помогло. Однако с введением INotifyDataErrorInfo интерфейс, я думал, что поэкспериментирую с ним, чтобы увидеть, есть ли какие-либо улучшения.

Пройдя несколько онлайн-уроков, я начал работать с различными ValidationAttributeс из System.ComponentModel.DataAnnotations namespace, Используя эти AttributeПозволяет вам предоставить основные правила проверки, как это:

[MinLength(3, ErrorMessage = "Name must be longer than 3 characters.")]
public string Name
{
    get { return name; }
    set { name = value; NotifyPropertyChanged("Name"); Validate("Name", name); }
}

Первоначально это выглядело довольно хорошо, так как сообщения об ошибках вставляются прямо в Valaidation.Errors Коллекция доступна в приложении ErrorTemplates. Тем не менее, большинство встроенных правил проверки действительно являются базовыми, и я привык применять сложные правила проверки, которые включают другие значения свойств.

Поэтому я решил найти способ создать простое правило проверки, включающее несколько свойств: правило, в котором должно быть установлено одно или два поля. Итак, я объявил класс, который расширил ValidationAttribute и после поиска в Интернете, нашел способ получить доступ к другим значениям свойств.

Я выбил базовый интерфейс с кастомом ErrorTemplate применяется к каждому TextBox, который отображал Validation.Errors коллекция для свойства привязки данных:

<ControlTemplate x:Key="ErrorTemplate">
    <StackPanel Orientation="Horizontal">
        <Border BorderBrush="#4FFF0000" BorderThickness="1" Margin="0,10">
            <AdornedElementPlaceholder />
        </Border>
        <Image Name="WarningImage" Source="pack://application:,,,/WpfApplication1;component/Images/Warning_16.png" Margin="5,0,0,0" Tag="{Binding}" />
        <Popup PlacementTarget="{Binding ElementName=WarningImage}" Placement="Right" Margin="5,0,0,0" AllowsTransparency="True" IsOpen="True">
            <Border BorderThickness="1" BorderBrush="#4FFF0000" CornerRadius="5" Background="White" Padding="5" Margin="10">
                <Border.Effect>
                    <DropShadowEffect Color="Red" Opacity="0.5" BlurRadius="15" ShadowDepth="0" />
                </Border.Effect>
                <ItemsControl ItemsSource="{Binding}">
                    <ItemsControl.ItemTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding ErrorContent}" />
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                </ItemsControl>
            </Border>
        </Popup>
    </StackPanel>
</ControlTemplate>

С моим обычаем Attribute установить на Name собственности, мне удалось добавить ValidationResult в Validation.Errors сбор через интерфейс, когда ни одно из свойств не было установлено, но вот проблема: если я добавлю значение в один из других TextBoxЕсли данные связаны с другими обязательными свойствами, сообщение об ошибке в первом TextBox останется там.

Если бы я вернулся к первому TextBox и что-то напечатало, тогда проверка работала бы, поэтому даже если я удалил значение, он все равно знал, что было установлено одно из обязательных свойств. Таким образом, код проверки работает, но проблема в том, что изменения свойств в других обязательных свойствах не запускают проверку в Name имущество.

Даже когда я применил тот же обычай Attribute с другими обязательными свойствами произошло то же самое... каждая ошибка проверки будет очищаться только при вводе соответствующего TextBox, Я также попробовал встроенный CustomValidationAttribute что позволяет нам вызывать метод в классе для проверки, но конечный результат был таким же.

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

1 ответ

Вот что я сделал, в классе, содержащем From а также To свойства. Я хотел подтвердить это From меньше или равно To,

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

    [CustomValidation(typeof(MyModel), "ValidateRange")]
    public double From
    {
        get
        {
            return _from;
        }
        set
        {
            if (_from != value)
            {
                _from = value;
                OnPropertyChanged("From");

                // Validate the other side
                ValidateProperty("To", _to);
            }
        }
    }

    [CustomValidation(typeof(MyModel), "ValidateRange")]
    public double To
    {
        get
        {
            return _to;
        }
        set
        {
            if (_to != value)
            {
                _to = value;
                OnPropertyChanged("To");

                // Validate the other side
                ValidateProperty("From", _from);
            }
        }
    }

    private static ValidationResult ValidateRange(ValidationContext validationContext)
    {
        var model = validationContext.ObjectInstance as MyModel;

        if (model.From > model.To)
        {
            return new ValidationResult("Invalid range");
        }

        return null;
    }

Как вы можете видеть, код в одном установщике свойств вызывает проверку свойства "прочее", точно так же, как вы упоминали в предыдущем абзаце. Нет причин, по которым он должен идти в бесконечный цикл, если только ваш код проверки не пытается установить одно из свойств, которое вызовет другой вызов Validate(), и так далее, и так далее.

Другие вопросы по тегам