Язык программирования C#9 и платформа .NET5
= new Dictionary<string, List<string>>();Свойство
должно возвращатьHasErrors, если в словаре присутствуют любые ошибки, что легко достигается следующим образом:truepublic bool HasErrors => _errors.Any();Создайте вспомогательный метод для инициирования события
(подобно инициированию событияErrorsChanged):PropertyChangedprivate void OnErrorsChanged(string propertyName){ErrorsChanged?.Invoke(this,new DataErrorsChangedEventArgs(propertyName));}Как упоминалось ранее, метод
должен возвращать любые ошибки в словаре, когда в параметре передается пустая строка илиGetErrors(). Если передается допустимое значениеnull, то возвращаются ошибки, обнаруженные для указанного свойства. Если параметр не соответствует какому-либо свойству (или ошибки для свойства отсутствуют), тогда метод возвратитpropertyName.nullpublic IEnumerable GetErrors(string propertyName){if (string.IsNullOrEmpty(propertyName)){return _errors.Values;}return _errors.ContainsKey(propertyName)? _errors[propertyName]: null;}Финальный набор вспомогательных методов будет добавлять одну или большее число ошибок для свойства либо очищать все ошибки для свойства (или всех свойств). Не следует забывать о вызове вспомогательного метода
каждый раз, когда словарь изменяется.OnErrorsChanged()private void AddError(string propertyName, string error){AddErrors(propertyName, new List<string> { error });}private void AddErrors(string propertyName, IList<string> errors){if (errors == null || !errors.Any()){return;}var changed = false;if (!_errors.ContainsKey(propertyName)){_errors.Add(propertyName, new List<string>());changed = true;}foreach (var err in errors){if (_errors[propertyName].Contains(err)) continue;_errors[propertyName].Add(err);changed = true;}if (changed){OnErrorsChanged(propertyName);}}protected void ClearErrors(string propertyName = ""){if (string.IsNullOrEmpty(propertyName)){_errors.Clear();}else{_errors.Remove(propertyName);}OnErrorsChanged(propertyName);}Возникает вопрос: когда приведенный выше код активизируется? Механизм привязки прослушивает событие
и обновляет пользовательский интерфейс, если в коллекции ошибок для выражения привязки возникает изменение. Но код проверки по-прежнему нуждается в триггере для запуска. Доступны два механизма, которые обсуждаются далее.ErrorsChangedИспользование интерфейса INotifyDataErrorInfo для проверки достоверности
Одним из мест выполнения проверки на предмет ошибок являются блоки
для свойств, как демонстрируется в показанном ниже примере, упрощенном до единственной проверки на равенство свойстваsetзначениюMake:ModelTpublic string Make{get { return _make; }set{if (value == _make) return;_make = value;if (Make == "ModelT"){AddError(nameof(Make), "Too Old");}else{ClearErrors(nameof(Make));}OnPropertyChanged(nameof(Make));OnPropertyChanged(nameof(Color));}}Основная проблема такого подхода состоит в том, что вам приходится сочетать логику проверки достоверности с блоками
для свойств, что делает код труднее в чтении и сопровождении.set