protected virtual void Dispose(bool disposing) { if (!_disposedValue) { if (disposing) { // TODO: dispose managed state (managed objects) if (_control != null) { _control.DataContextChanged -= Control_DataContextChanged; _control.TryDispose(); _control = null; } if (_viewModel != null) { _viewModel.ErrorsChanged -= NotifyDataErrorInfo_ErrorsChanged; _viewModel = null; } if (_errorPopup != null) { _errorPopup.TryDispose(); _errorPopup = null; } } // TODO: free unmanaged resources (unmanaged objects) and override finalizer // TODO: set large fields to null _disposedValue = true; } }
internal WeakErrorsChangedListener(INotifyDataErrorInfo notifyDataErrorInfo, bool notifyChild, IErrorsChangedListener errorsChangedListener) { this.notifyDataErrorInfo = notifyDataErrorInfo; this.notifyChild = notifyChild; notifyDataErrorInfo.ErrorsChanged += new EventHandler <DataErrorsChangedEventArgs>(this.ErrorsChangedCallback); this.weakErrorsChangedListener = new WeakReference(errorsChangedListener); }
private void UpdateErrors(INotifyDataErrorInfo newViewModel) { if (_errorsGrid == null || _errorList == null || _title == null) { return; } if (newViewModel == null) { return; } var allErrors = newViewModel.GetErrors(ValidatingBase.AllErrorsToken).Cast <string>(); if (allErrors.Any()) { this.Log().Debug($"We have errors - {allErrors.Count()}"); _errorsGrid.Visibility = Visibility.Visible; _title.Text = $"{allErrors.Count()} error{(allErrors.Count() > 1 ? "s" : "")}"; _boundErrors.Clear(); foreach (var error in allErrors) { _boundErrors.Add(error); } } else { _errorsGrid.Visibility = Visibility.Collapsed; } }
private static void UpdateValidationContent(string propertyName, INotifyDataErrorInfo context, ContentControl validationPlaceholder) { IEnumerable <string> errors = context.GetErrors(propertyName).OfType <string>(); validationPlaceholder.Content = errors; validationPlaceholder.Visibility = errors.Any() ? Visibility.Visible : Visibility.Collapsed; }
public void ValidateMethodShouldCallNotifyEvent() { ThreadManager.ImmediateInvokeAsync = true; ThreadManager.ImmediateInvokeOnUiThreadAsync = true; ThreadManager.ImmediateInvokeOnUiThread = true; int countInvoke = 0; ValidatableViewModel viewModel = GetValidatableViewModel(); INotifyDataErrorInfo notifyDataError = viewModel; notifyDataError.ErrorsChanged += (sender, args) => { args.PropertyName.ShouldEqual(PropToValidate1); countInvoke++; }; var validator = viewModel.AddValidator <SpyValidator>(new object()); notifyDataError.HasErrors.ShouldBeFalse(); validator.SetErrors(PropToValidate1, PropToValidate1); countInvoke.ShouldEqual(1); validator.SetErrors(PropToValidate1, PropToValidate2); countInvoke.ShouldEqual(2); notifyDataError.HasErrors.ShouldBeTrue(); //NOTE: Event is not invoked, if errors is not changed. /*viewModel.ValidateAsync(PropToValidate1); * countInvoke.ShouldEqual(2);*/ }
public void ImplementsINotifyDataErrorInfo() { TestViewModel viewModel = GivenViewModel(); INotifyDataErrorInfo notify = GivenNotifyDataErrorInfo(viewModel); notify.Should().NotBeNull(); }
internal WeakErrorsChangedListener(INotifyDataErrorInfo notifyDataErrorInfo, bool notifyChild, IErrorsChangedListener errorsChangedListener) { this.notifyDataErrorInfo = notifyDataErrorInfo; this.notifyChild = notifyChild; notifyDataErrorInfo.ErrorsChanged += new EventHandler<DataErrorsChangedEventArgs>(this.ErrorsChangedCallback); this.weakErrorsChangedListener = new WeakReference(errorsChangedListener); }
public void ValidateMethodShouldRaiseErrorsChangedEvent() { int countInvoke = 0; ValidatorBase validator = GetValidator(); INotifyDataErrorInfo notifyDataError = validator; notifyDataError.ErrorsChanged += (sender, args) => { args.PropertyName.ShouldEqual(PropertyToValidate); countInvoke++; }; validator.Initialize(new ValidatorContext(new object(), GetServiceProvider())); notifyDataError.HasErrors.ShouldBeFalse(); validator.UpdateErrors(PropertyToValidate, ValidatorErrors, false); countInvoke.ShouldEqual(1); notifyDataError.HasErrors.ShouldBeTrue(); if (validator is ManualValidator) { validator.UpdateErrors(PropertyToValidate, ValidatorErrors, false); } else { validator.ValidateAsync(PropertyToValidate); } countInvoke.ShouldEqual(2); }
public TextViewErrorBinding(TextView target, INotifyDataErrorInfo sourceObject, string sourceProperty) : base(target) { _target = target; _sourceObject = sourceObject; _sourceProperty = sourceProperty; _sourceObject.ErrorsChanged += sourceObject_ErrorsChanged; }
/// <summary> /// Remove a handler for the given source's event. /// </summary> public static void RemoveHandler(INotifyDataErrorInfo source, EventHandler<DataErrorsChangedEventArgs> handler) { if (source == null) throw new ArgumentNullException("source"); if (handler == null) throw new ArgumentNullException("handler"); CurrentManager.ProtectedRemoveHandler(source, handler); }
public ErrorInfoHandler(FrameworkElement element, INotifyDataErrorInfo errorInfo, DependencyProperty dp) { _element = element; _bindingExpr = element.GetBindingExpression(dp); // ReSharper disable once PossibleNullReferenceException _propertyName = _bindingExpr.ResolvedSourcePropertyName; _errorInfo = errorInfo; _errorsContainer = errorInfo as IPropertyErrorsContainer; }
/// <summary> /// Checks the value core. /// </summary> /// <param name="validation">The validation.</param> /// <exception cref="ValidationException"></exception> protected static void CheckValueCore(INotifyDataErrorInfo validation) { if (validation == null) throw new ArgumentNullException(nameof(validation), $"{nameof(validation)} is null."); if (validation.HasErrors) throw new ValidationException($"Validation errors: " + string.Join(Environment.NewLine + " ", validation.GetErrors(null).OfType<object>().Select(e => e.ToString()))); }
private static void SetDataErrorInfoBinding(this DependencyObject element, INotifyDataErrorInfo dataErrorInfo) { Debug.Assert(dataErrorInfo != null); var binding = new System.Windows.Data.Binding(".") { Source = dataErrorInfo, Mode = BindingMode.TwoWay, ValidatesOnNotifyDataErrors = true }; BindingOperations.SetBinding(element, DummyProperty, binding); }
internal void Disconnect() { if (this.notifyDataErrorInfo == null) { return; } this.notifyDataErrorInfo.ErrorsChanged -= new EventHandler<DataErrorsChangedEventArgs>(this.ErrorsChangedCallback); this.notifyDataErrorInfo = null; this.weakErrorsChangedListener = null; }
internal void Disconnect() { if (this.notifyDataErrorInfo == null) { return; } this.notifyDataErrorInfo.ErrorsChanged -= new EventHandler <DataErrorsChangedEventArgs>(this.ErrorsChangedCallback); this.notifyDataErrorInfo = null; this.weakErrorsChangedListener = null; }
public void Entity_EndEditValidatesEntity() { TestEntity invalidEntity = new TestEntity(); ((IEditableObject)invalidEntity).BeginEdit(); invalidEntity.ID1 = "1"; invalidEntity.ID2 = "1"; string expectedError = "TestEntity is not valid."; #if SILVERLIGHT INotifyDataErrorInfo notifier = (INotifyDataErrorInfo)invalidEntity; // Track what errors existed for the property name at the time of each event var actualErrors = new List <Tuple <string, IEnumerable <ValidationResult> > >(); notifier.ErrorsChanged += (s, e) => { actualErrors.Add(Tuple.Create(e.PropertyName, notifier.GetErrors(e.PropertyName).Cast <ValidationResult>())); }; ((IEditableObject)invalidEntity).EndEdit(); Assert.AreEqual <int>(1, actualErrors.Count, "There should have been a single ErrorsChanged event"); Tuple <string, IEnumerable <ValidationResult> > error = actualErrors[0]; Assert.AreEqual <string>(null, error.Item1, "The error should have been an entity-level error (null PropertyName)"); Assert.AreEqual <int>(1, error.Item2.Count(), "There should have been a single error at the time of the event"); Assert.AreEqual <string>(expectedError, error.Item2.First().ErrorMessage, "The error message of the single error didn't match the expectation"); // Clear out the errors for the next stage of the test actualErrors.Clear(); #else ExceptionHelper.ExpectException <ValidationException>(delegate { ((IEditableObject)invalidEntity).EndEdit(); }, expectedError); ((IEditableObject)invalidEntity).CancelEdit(); Assert.IsNull(invalidEntity.ID1); Assert.IsNull(invalidEntity.ID2); #endif TestEntity validEntity = new TestEntity(); ((IEditableObject)validEntity).BeginEdit(); validEntity.ID1 = "1"; validEntity.ID2 = "2"; ((IEditableObject)validEntity).EndEdit(); Assert.AreEqual("1", validEntity.ID1); Assert.AreEqual("2", validEntity.ID2); #if SILVERLIGHT Assert.AreEqual <int>(0, actualErrors.Count, "There should not have been any errors during the valid EndEdit()"); #endif }
protected override void OnDetaching() { base.OnDetaching(); INotifyDataErrorInfo validation = FindValidation(Target); if (validation != null) { validation.ErrorsChanged -= OnValidationErrorsChanges; } Target.MouseLeftButtonUp -= OnConfirm; }
public static void NotifiesNoDataError(string propertyName, INotifyDataErrorInfo target, Action action) { var listener = Substitute.For <EventHandler <DataErrorsChangedEventArgs> >(); target.ErrorsChanged += listener; action.Invoke(); target.ErrorsChanged -= listener; listener.Received() .Invoke(Arg.Is(target), Arg.Is <DataErrorsChangedEventArgs>(args => args.PropertyName == propertyName)); Empty(target.GetErrors(propertyName)); }
protected override void OnAttached() { base.OnAttached(); INotifyDataErrorInfo validation = FindValidation(Target); if (validation != null) { Target.IsEnabled = !validation.HasErrors; validation.ErrorsChanged += OnValidationErrorsChanges; } Target.PreviewMouseLeftButtonUp += OnConfirm; }
private static void OnDataContextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { INotifyDataErrorInfo context = e.OldValue as INotifyDataErrorInfo; if (context != null) { RemoveHandler(d, context); SetIsValidationAttached(d, false); } OnValidationPropertyChanged(d, e); }
/// <summary> /// Remove a handler for the given source's event. /// </summary> public static void RemoveHandler(INotifyDataErrorInfo source, EventHandler <DataErrorsChangedEventArgs> handler) { if (source == null) { throw new ArgumentNullException("source"); } if (handler == null) { throw new ArgumentNullException("handler"); } CurrentManager.ProtectedRemoveHandler(source, handler); }
private void Control_DataContextChanged(DependencyObject sender, DataContextChangedEventArgs args) { if (args.NewValue is INotifyDataErrorInfo notifyDataErrorInfo) { if (_viewModel != null) { _viewModel.ErrorsChanged -= NotifyDataErrorInfo_ErrorsChanged; } _viewModel = notifyDataErrorInfo; notifyDataErrorInfo.ErrorsChanged += NotifyDataErrorInfo_ErrorsChanged; } }
private void RegisterValidationChangedEvent() { object SourceItem = this.BindingExpression.PrivateMembers().GetProperty <object>("SourceItem"); this.notifyDataErrorSourceItem = SourceItem as INotifyDataErrorInfo; this.dataErrorSourceItem = SourceItem as IDataErrorInfo; this.sourcePropertyName = this.BindingExpression.PrivateMembers().GetProperty <string>("SourcePropertyName"); if (this.notifyDataErrorSourceItem != null) { this.notifyDataErrorSourceItem.ErrorsChanged += this.ErrorsChanged; } }
/// <summary> /// Checks the value core. /// </summary> /// <param name="validation">The validation.</param> /// <exception cref="ValidationException"></exception> protected static void CheckValueCore(INotifyDataErrorInfo validation) { if (validation == null) { throw new ArgumentNullException(nameof(validation), $"{nameof(validation)} is null."); } if (validation.HasErrors) { throw new ValidationException($"Validation errors: " + string.Join(Environment.NewLine + " ", validation.GetErrors(null).OfType <object>().Select(e => e.ToString()))); } }
/// <summary> /// Method will subscibe and unsubsribe Error changed event /// Get bindable property path of text property /// </summary> public void CheckValidation() { // Reset variables values ErrorMessage = ""; HasError = false; BindingPath = ""; if (_NotifyErrors != null) { // Unsubscribe event _NotifyErrors.ErrorsChanged += _NotifyErrors_ErrorsChanged; _NotifyErrors = null; // Set null value on binding context change } // Remove notify scroll to property if (_NotifyScroll != null) { _NotifyScroll.ScrollToProperty -= NotifyScroll_ScrollToProperty; _NotifyScroll = null; } // Do nothing if show error message property value is false if (!this.ShowErrorMessage || this.View is null) { return; } if (this.View.BindingContext != null && this.View.BindingContext is INotifyDataErrorInfo) { // Get _NotifyErrors = this.View.BindingContext as INotifyDataErrorInfo; if (_NotifyErrors == null) { return; } // Subscribe event _NotifyErrors.ErrorsChanged += _NotifyErrors_ErrorsChanged; // Remove notify scroll to property if (this.View.BindingContext is INotifyScrollToProperty) { _NotifyScroll = this.View.BindingContext as INotifyScrollToProperty; _NotifyScroll.ScrollToProperty += NotifyScroll_ScrollToProperty; } this.BindingPath = this.View.GetBindingPath(BindableProperty); SetPlaceHolder(); } }
/// <summary> /// 指定したViewModelオブジェクトの持つエラー情報をすべてコンソールに出力します。 /// </summary> /// <param name="viewModel">コンソールに出力するViewModelオブジェクト</param> private void ConsoleWriteErrorMessages(INotifyDataErrorInfo viewModel) { if ((viewModel != null) && viewModel.HasErrors) { var properties = viewModel.GetType().GetProperties(); foreach (var property in properties) { foreach (var error in viewModel.GetErrors(property.Name)) { Output.WriteLine($"{viewModel.GetType().Name}.{property.Name} - {error}"); } } } }
public void EntityRefValidation() { City invalidCity = new City(); ValidationContext ctxt = new ValidationContext(invalidCity, null, null) { MemberName = "City" }; Assert.AreNotEqual(Cities.CityPropertyValidator.IsValidCity(invalidCity, ctxt), ValidationResult.Success); Zip zip = new Zip() { Code = 98053, FourDigit = 8625, CityName = "Redmond", CountyName = "King", StateName = "WA" }; INotifyDataErrorInfo notifier = (INotifyDataErrorInfo)zip; List <string> actualErrors = new List <string>(); notifier.ErrorsChanged += (s, e) => { actualErrors.Add(e.PropertyName); }; zip.City = invalidCity; // With INotifyDataErrorInfo validation, the property will get set, even though it's invalid Assert.AreEqual <City>(invalidCity, zip.City, "The value should have been set"); Assert.IsTrue(actualErrors.SequenceEqual(new string[] { "City", "CityName", "StateName" }), "Expected errors from the City, CityName, and StateName properties on the Zip entity."); // Verify that we have the expected validation error for the property IEnumerable <ValidationResult> results = zip.ValidationErrors.Where(e => e.MemberNames.Contains("City")); Assert.AreEqual <int>(1, results.Count(), "Expected a single error for the property"); // set to a valid City - expect success City validCity = new City { Name = "Toledo", CountyName = "Lucas", StateName = "OH" }; zip.City = validCity; }
private IEnumerable <Validation> GetErrors(INotifyDataErrorInfo viewModel) { var enumerable = viewModel.GetErrors(null); foreach (var item in enumerable) { if (item is Validation validation) { yield return(validation); } else { yield return(Validation.Error(item.ToString())); } } }
private static string AddHandler(DependencyObject d, INotifyDataErrorInfo context, ContentControl placeholder) { string property = GetProperty(d); EventHandler <DataErrorsChangedEventArgs> contextOnErrorsChanged = (sender, args) => { if (args.PropertyName == property) { UpdateValidationContent(property, context, placeholder); } }; SetEventHandler(d, contextOnErrorsChanged); context.ErrorsChanged += contextOnErrorsChanged; return(property); }
public void TestExplicitGetErrors() { var vm = new TestViewModel(); vm.AddValidationRule <int>(nameof(vm.AProperty), x => new ValidationRuleResult(true, "error")); INotifyDataErrorInfo indei = vm; object[] indeiErrors = indei .GetErrors(nameof(vm.AProperty)) .Cast <object>() .ToArray(); string[] errors = vm.GetErrors(nameof(vm.AProperty)).ToArray(); CollectionAssert.AreEqual(errors, indeiErrors); }
internal void OnDataErrorsChanged(INotifyDataErrorInfo indei, string propName) { // if notification was on the right thread, just do the work (normal case) if (Dispatcher.Thread == Thread.CurrentThread) { ParentBindingExpression.UpdateNotifyDataErrors(indei, propName, DependencyProperty.UnsetValue); } else if (!ParentBindingExpression.IsDataErrorsChangedPending) { // otherwise invoke an operation to do the work on the right context ParentBindingExpression.IsDataErrorsChangedPending = true; Engine.Marshal( (arg) => { object[] args = (object[])arg; ParentBindingExpression.UpdateNotifyDataErrors((INotifyDataErrorInfo)args[0], (string)args[1], DependencyProperty.UnsetValue); return(null); }, new object[] { indei, propName }); } }
private static void OnValidationPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { // Check if validation is already attached to the property bool isValidationAttached = GetIsValidationAttached(d); if (isValidationAttached) { return; } string property = GetProperty(d); ContentControl placeholder = GetValidationPlaceholder(d); INotifyDataErrorInfo context = GetDataContext(d) as INotifyDataErrorInfo; if (!string.IsNullOrEmpty(property) && placeholder != null && context != null) { SetIsValidationAttached(d, true); } }
public void NotifyDataErrorInfoShouldGetErrorsFromValidators() { ValidatableViewModel viewModel = GetValidatableViewModel(); INotifyDataErrorInfo notifyDataError = viewModel; var validator = viewModel.AddValidator <SpyValidator>(new object()); notifyDataError.HasErrors.ShouldBeFalse(); validator.SetErrors(PropToValidate1, PropToValidate1, PropToValidate2); notifyDataError.HasErrors.ShouldBeTrue(); string[] errors = notifyDataError.GetErrors(PropToValidate1).OfType <string>().ToArray(); errors.Length.ShouldEqual(2); errors.Contains(PropToValidate1).ShouldBeTrue(); errors.Contains(PropToValidate2).ShouldBeTrue(); validator.SetErrors(PropToValidate1); notifyDataError.GetErrors(PropToValidate1).ShouldBeEmpty(); notifyDataError.HasErrors.ShouldBeFalse(); }
private void UpdateErrors(INotifyDataErrorInfo viewModel) { ClearErrors(); var validations = GetErrors(viewModel).ToList(); foreach (var validation in validations.Where(x => x.Severity == Validation.IssueSeverity.Error)) { Errors.Add(validation); } foreach (var validation in validations.Where(x => x.Severity == Validation.IssueSeverity.Warning)) { Warnings.Add(validation); } HasIssues = validations.Any(); HasWarnings = Warnings.Any(); HasErrors = Errors.Any(); }
private static void CollectErrors(INotifyDataErrorInfo notifyDataErrorInfo, string path, ref List <object> errors) { var values = notifyDataErrorInfo.GetErrors(path ?? string.Empty); if (values == null) { return; } foreach (var error in values) { if (error == null) { continue; } if (errors == null) { errors = new List <object>(); } errors.Add(error); } }
void AttachToNotifyError (INotifyDataErrorInfo element) { if (CurrentNotifyError == element || !Binding.ValidatesOnNotifyDataErrors) return; string property = ""; if (PropertyPathWalker.FinalNode.PropertyInfo != null) property = PropertyPathWalker.FinalNode.PropertyInfo.Name; if (CurrentNotifyError != null) { CurrentNotifyError.ErrorsChanged -= NotifyErrorsChanged; MaybeEmitError (null, null); } CurrentNotifyError = element; if (CurrentNotifyError != null) { CurrentNotifyError.ErrorsChanged += NotifyErrorsChanged; if (CurrentNotifyError.HasErrors) { foreach (var v in CurrentNotifyError.GetErrors (property)) { MaybeEmitError (v as string, v as Exception); } } else { MaybeEmitError (null, null); } } }
// fetch errors for the given property internal static List<object> GetDataErrors(INotifyDataErrorInfo indei, string propertyName) { const int RetryCount = 3; List<object> result = null; if (indei != null && indei.HasErrors) { // if a worker thread is updating the source's errors while we're trying to // read them, the enumerator will throw. The interface doesn't provide // any way to work around this, so we'll just try it a few times hoping // for success. for (int i=RetryCount; i>=0; --i) { try { result = new List<object>(); IEnumerable ie = indei.GetErrors(propertyName); if (ie != null) { foreach (object o in ie) { result.Add(o); } } break; } catch (InvalidOperationException) { // on the last try, let the exception bubble up if (i == 0) throw; } } } if (result != null && result.Count == 0) result = null; return result; }
// fetch the current data errors from the source object (and its value), // and update the list of data-error ValidationResults accordingly internal void UpdateNotifyDataErrors(INotifyDataErrorInfo indei, string propertyName, object value) { if (!ValidatesOnNotifyDataErrors || IsDetached) return; // replace the value object, if it has changed WeakReference dataErrorWR = (WeakReference)GetValue(Feature.DataErrorValue, null); INotifyDataErrorInfo dataErrorValue = (dataErrorWR == null) ? null : dataErrorWR.Target as INotifyDataErrorInfo; if (value != DependencyProperty.UnsetValue && value != dataErrorValue && IsDynamic) { if (dataErrorValue != null) ErrorsChangedEventManager.RemoveHandler(dataErrorValue, OnErrorsChanged); INotifyDataErrorInfo newDataErrorValue = value as INotifyDataErrorInfo; object newDataErrorWR = ReplaceReference(dataErrorWR, newDataErrorValue); SetValue(Feature.DataErrorValue, newDataErrorWR, null); dataErrorValue = newDataErrorValue; if (newDataErrorValue != null) ErrorsChangedEventManager.AddHandler(newDataErrorValue, OnErrorsChanged); } // fetch the errors from the last item and from its value IsDataErrorsChangedPending = false; try { List<object> propertyErrors = GetDataErrors(indei, propertyName); List<object> valueErrors = GetDataErrors(dataErrorValue, String.Empty); List<object> errors = MergeErrors(propertyErrors, valueErrors); UpdateNotifyDataErrorValidationErrors(errors); } catch (Exception ex) { // if GetErrors or the enumerators throw, leave the old errors in place if (CriticalExceptions.IsCriticalApplicationException(ex)) throw; } }
private void GetNotifyDataErrorInfoInstances(out string propertyName, out INotifyDataErrorInfo notifyDataErrorInfo, out INotifyDataErrorInfo notifyChildDataErrorInfo) { propertyName = null; notifyDataErrorInfo = null; notifyChildDataErrorInfo = null; if (this.listener != null && this.listener.FullPathExists) { notifyDataErrorInfo = this.listener.LeafItem as INotifyDataErrorInfo; if (notifyDataErrorInfo != null) { propertyName = this.listener.LeafPropertyName; } if (this.listener.LeafProperty != null) { notifyChildDataErrorInfo = this.listener.LeafValue as INotifyDataErrorInfo; } } }
/// <summary> /// Checks an INDEI data object for errors on the specified path. New errors are added to the /// list of validation results. /// </summary> /// <param name="indei">INDEI object to validate.</param> /// <param name="bindingProperty">Name of the property to validate.</param> /// <param name="bindingPath">Path of the binding.</param> /// <param name="declaringPath">Path of the INDEI object.</param> /// <param name="validationResults">List of results to add to.</param> /// <param name="wireEvents">True if the ErrorsChanged event should be subscribed to.</param> private void ValidateIndei(INotifyDataErrorInfo indei, string bindingProperty, string bindingPath, string declaringPath, List<ValidationResult> validationResults, bool wireEvents) { if (indei != null) { if (indei.HasErrors) { IEnumerable errors = null; ValidationUtil.CatchNonCriticalExceptions(() => { errors = indei.GetErrors(bindingProperty); }); if (errors != null) { foreach (object errorItem in errors) { if (errorItem != null) { string errorString = null; ValidationUtil.CatchNonCriticalExceptions(() => { errorString = errorItem.ToString(); }); if (!string.IsNullOrEmpty(errorString)) { ValidationResult validationResult; if (!string.IsNullOrEmpty(bindingProperty)) { validationResult = new ValidationResult(errorString, new List<string>() { bindingPath }); this._propertyValidationResults.Add(validationResult); } else { Debug.Assert(string.IsNullOrEmpty(bindingPath)); validationResult = new ValidationResult(errorString); } validationResults.AddIfNew(validationResult); this._indeiValidationResults.AddIfNew(validationResult); } } } } } if (wireEvents) { indei.ErrorsChanged += new EventHandler<DataErrorsChangedEventArgs>(ValidationItem_ErrorsChanged); if (!this._validationItems.ContainsKey(indei)) { this._validationItems.Add(indei, declaringPath); } } } }
internal void OnDataErrorsChanged(INotifyDataErrorInfo indei, string propName) { // if notification was on the right thread, just do the work (normal case) if (Dispatcher.Thread == Thread.CurrentThread) { ParentBindingExpression.UpdateNotifyDataErrors(indei, propName, DependencyProperty.UnsetValue); } else if (!ParentBindingExpression.IsDataErrorsChangedPending) { // otherwise invoke an operation to do the work on the right context ParentBindingExpression.IsDataErrorsChangedPending = true; Engine.Marshal( (arg) => { object[] args = (object[])arg; ParentBindingExpression.UpdateNotifyDataErrors((INotifyDataErrorInfo)args[0], (string)args[1], DependencyProperty.UnsetValue); return null; }, new object[]{indei, propName}); } }
private void UpdateNotifyDataErrorInfos() { INotifyDataErrorInfo notifyDataErrorInfo; INotifyDataErrorInfo notifyDataErrorInfo1; INotifyDataErrorInfo notifyDataErrorInfo2; INotifyDataErrorInfo notifyDataErrorInfo3; if (this.binding.ValidatesOnNotifyDataErrors) { string str = null; this.GetNotifyDataErrorInfoInstances(out str, out notifyDataErrorInfo, out notifyDataErrorInfo1); bool flag = notifyDataErrorInfo != this.currentNotifyDataErrorInfo; bool flag1 = notifyDataErrorInfo1 != this.currentNotifyChildDataErrorInfo; if (flag || flag1) { this.ResetNotifyDataErrorInfo(flag, flag1); this.currentNotifyDataErrorInfo = notifyDataErrorInfo; this.currentNotifyChildDataErrorInfo = notifyDataErrorInfo1; string str1 = str; if (flag) { notifyDataErrorInfo2 = this.currentNotifyDataErrorInfo; } else { notifyDataErrorInfo2 = null; } if (flag1) { notifyDataErrorInfo3 = this.currentNotifyChildDataErrorInfo; } else { notifyDataErrorInfo3 = null; } this.ConsumeNotifyDataErrorInfo(str1, notifyDataErrorInfo2, notifyDataErrorInfo3); } } }
private void NotifyNewDataErrorInfos(string propertyName, INotifyDataErrorInfo notifyDataErrorInfo, bool isNotifyChildDataErrorInfo) { IEnumerable errors = null; try { errors = notifyDataErrorInfo.GetErrors(propertyName); } catch (Exception e) { Debug.WriteLine(e.ToString()); if (e is OutOfMemoryException || e is StackOverflowException || e is AccessViolationException || e is ThreadAbortException) { throw; } } this.NotifyNewDataErrorInfos(this.RegisterErrorCollection(propertyName, errors, isNotifyChildDataErrorInfo)); }
private void ResetNotifyDataErrorInfo(bool resetCurrentNotifyDataErrorInfo, bool resetCurrentNotifyChildDataErrorInfo) { if (resetCurrentNotifyDataErrorInfo & this.currentNotifyDataErrorInfo != null) { if (this.errorsChangedListener != null) { this.errorsChangedListener.Disconnect(); this.errorsChangedListener = null; } this.currentNotifyDataErrorInfo = null; } if (resetCurrentNotifyChildDataErrorInfo && this.currentNotifyChildDataErrorInfo != null) { if (this.childErrorsChangedListener != null) { this.childErrorsChangedListener.Disconnect(); this.childErrorsChangedListener = null; } this.currentNotifyChildDataErrorInfo = null; } if (resetCurrentNotifyDataErrorInfo) { this.NotifyOldDataErrorInfos(false); } if (resetCurrentNotifyChildDataErrorInfo) { this.NotifyOldDataErrorInfos(true); } }
private void ConsumeNotifyDataErrorInfo(string propertyName, INotifyDataErrorInfo notifyDataErrorInfo, INotifyDataErrorInfo notifyChildDataErrorInfo) { if (notifyDataErrorInfo != null && this.binding.Mode != BindingMode.OneTime) { this.errorsChangedListener = new WeakErrorsChangedListener(notifyDataErrorInfo, false, this); } if (notifyChildDataErrorInfo != null && this.binding.Mode != BindingMode.OneTime) { this.childErrorsChangedListener = new WeakErrorsChangedListener(notifyChildDataErrorInfo, true, this); } if (notifyDataErrorInfo != null) { this.NotifyNewDataErrorInfos(propertyName, notifyDataErrorInfo, false); } if (notifyChildDataErrorInfo != null) { this.NotifyNewDataErrorInfos(string.Empty, notifyChildDataErrorInfo, true); } }
private static void CollectErrors(INotifyDataErrorInfo notifyDataErrorInfo, string path, ref List<object> errors) { var values = notifyDataErrorInfo.GetErrors(path ?? string.Empty); if (values == null) return; foreach (var error in values) { if (error == null) continue; if (errors == null) errors = new List<object>(); errors.Add(error); } }