WPF Как вручную установить свойство Validation.HasError для элементов управления? - PullRequest
0 голосов
/ 03 октября 2018

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

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

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

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

1 Ответ

0 голосов
/ 08 октября 2018

Когда мы проверяем свойство, не просматривая его.Он не будет обновлять свойство 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);
    }
}
...