WPF Как вручную установить свойство Validation.HasError для элементов управления?

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

Но я хочу, чтобы все ошибки валидации отображались на экране вручную, когда пользователь нажимает кнопку "Сохранить", не обращаясь к элементам управления, в противном случае, как это выглядит, если пользователь загружает экран и нажимает кнопку "Сохранить".

Даже если я создаю метод, такой как IsValid (), и вызываю его после нажатия кнопки "Сохранить", он проверяет всю форму и сообщает мне, действительна она или нет, но красная рамка вокруг текстовых полей не будет отображаться (потому что Валидация). Свойство HasError не обновляется), что мне нужно, потому что в форме нескольких элементов управления мне нужно уведомить пользователя о точном элементе управления, который вызывает проблему.

Вы можете получить пример проекта с проблемой по этой ссылке https://1drv.ms/u/s!AuCr-YEWkmWUiopdQ-eZ17IC7IAJnA

1 ответ

Решение

Когда мы проверяем свойство, не просматривая его. Он не будет обновлять свойство Validate.HasError элемента управления. Решение этой проблемы было простым старым простым NotifyPropertyChanged (propertyName).

Я использовал NotifyPropertyChanged когда значение моего свойства изменяется (в наборе), но не обходя его, оно никогда не срабатывает.

Так что либо мы должны позвонить NotifyPropertyChanged когда проверка свойства не удалась или мы должны позвонить NotifyPropertyChanged(null) которые уведомляют все элементы управления, чтобы обновить их свойства.

Добавление полной реализации моего INotifyDataErrorInfo

    public class NotifyDataErrorInfoBase<T> : INotifyDataErrorInfo
{
    public NotifyDataErrorInfoBase(T model)
    {
        Model = model;
    }

    public T Model { get; set; }

    protected void SetValue<TValue>(string propertyName, TValue value)
    {
        typeof(T).GetProperty(propertyName).SetValue(Model, value);
        ValidateProperty<TValue>(propertyName);
    }

    public bool ValidateAllProperties()
    {

        List<KeyValuePair<string, Type>> lstOfProperties = typeof(T).GetProperties().
             Select(u => new KeyValuePair<string, Type>(u.Name, u.PropertyType)).ToList();
        foreach (var property in lstOfProperties)
        {
           Type currentType = property.Value;
            if (property.Value == typeof(string))
            {
                ValidateProperty<string>(property.Key);
            }
            else if (property.Value == typeof(int))
            {
                ValidateProperty<int>(property.Key);
            }
        }
        return !HasErrors;
    }

    private void ValidateProperty<TValue>([CallerMemberName]string propertyName = null)
    {
        ClearErrors(propertyName);
        var validationContext = new ValidationContext(Model) { MemberName = propertyName };
        List<ValidationResult> results = new List<ValidationResult>();

        var userName = GetValue<TValue>(propertyName);
        Validator.TryValidateProperty(userName, validationContext, results);

        if (results.Any())
        {
            foreach (var item in results)
            {
                AddError(propertyName, item.ErrorMessage);
            }
        }
    }

    protected TValue GetValue<TValue>(string propertyName)
    {
        return (TValue)typeof(T).GetProperty(propertyName).GetValue(Model);
    }

    Dictionary<string, List<string>> _lstOfErrors = new Dictionary<string, List<string>>();

    public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;

    public bool HasErrors => _lstOfErrors.Any();

    public IEnumerable GetErrors(string propertyName)
    {
        return _lstOfErrors.ContainsKey(propertyName) ? _lstOfErrors[propertyName] : null;
    }

    protected void AddError(string propertyName, string errorMessage)
    {
        if (!_lstOfErrors.ContainsKey(propertyName))
        {
            _lstOfErrors[propertyName] = new List<string>();
        }
        _lstOfErrors[propertyName].Add(errorMessage);
    }

    protected void OnErrorsChanged(string propertyName)
    {
        ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(propertyName));
    }

    protected void ClearErrors(string propertyName)
    {
        if (_lstOfErrors.ContainsKey(propertyName))
            _lstOfErrors.Remove(propertyName);
    }
}
Другие вопросы по тегам