void OnCollectionChanged(TOwner owner, string propertyName, NotifyCollectionChangedEventArgs e) { var successful = true; var notifyChangeOnValidationError = true; var descriptor = ViewModelBase <TOwner> .RegisterCollectionProperty <TResult>(propertyName); if (descriptor is null) { throw new InvalidOperationException("Raw property found where collection property expected. Try using RegisterCollectionProperty instead of RegisterProperty"); } var scopeContext = owner.ActiveScope?.CurrentScopeContext; ValidationResults.Clear(); foreach (var record in descriptor.ValidationRecords) { var validateFunc = record.Validate; var success = DoValidate(owner, Collection, validateFunc); if (!success) { owner.OnErrorChanged(propertyName); if (!record.ContinueOnValidationError) { return; } } successful &= success; notifyChangeOnValidationError &= record.NotifyChangeOnValidationError; } foreach (var action in descriptor.ChangedActions) { action?.Invoke(Collection); } if (successful || notifyChangeOnValidationError) { PropertyNotificationScopeAspect.TryRecordOrElseNotify(scopeContext, owner, propertyName, e, descriptor.IsRecordingEnabled); } return; }
internal bool SetValue(TOwner owner, string propertyName, TResult value) { var successful = true; var notifyChangeOnValidationError = true; var descriptor = ViewModelBase <TOwner> .RegisterProperty <TResult>(propertyName); var scopeContext = owner.ActiveScope?.CurrentScopeContext; bool validate(Func <ViewModelPropertyDescriptor <TOwner, TResult> .ValidationRecord, bool> predicate) { foreach (var record in descriptor.ValidationRecords.Where(predicate)) { var validateFunc = record.Validate; var success = DoValidate(owner, value, validateFunc); if (!success) { owner.OnErrorChanged(propertyName); if (!record.ContinueOnValidationError) { return(false); } } successful &= success; notifyChangeOnValidationError &= record.NotifyChangeOnValidationError; } return(true); } // Clear all previous validations before revalidate property ValidationResults.Clear(); // Validations before coerce if (!validate(x => x.BehaviorOnCoerce == ValidationErrorBehavior.BeforeCoerce || x.BehaviorOnCoerce == ValidationErrorBehavior.BeforeAndAfterCoerce)) { return(false); } // coerces foreach (var coerce in descriptor.Coerces) { if (successful && coerce != null) { value = coerce(value); } } // If no change, there is nothing else to do var oldValue = Value; if (Equals(oldValue, value)) { return(false); } // Validations after coerce, if such if (!validate(x => x.BehaviorOnCoerce == ValidationErrorBehavior.AfterCoerce || x.BehaviorOnCoerce == ValidationErrorBehavior.BeforeAndAfterCoerce)) { return(false); } // New value asigned Value = value; foreach (var setter in descriptor.Setters) { setter?.Invoke(value); } // Record and notification if (successful || notifyChangeOnValidationError) { PropertyNotificationScopeAspect.TryRecordOrElseNotify(scopeContext, owner, propertyName, oldValue, value, descriptor.IsRecordingEnabled); } return(true); }