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;
        }
예제 #2
0
        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);
        }