public void HandleChange(IBehaviorContext context, ChangeArgs args)
        {
            // We eagerly refresh the caches of all ancestors. Consider the case:
            //   (1) A validation result change is notified, thus all caches up the
            //       hierarchy hold invalid validation states.
            //   (2) The next behavior in this chain may access the cached validation
            //       result of an ancestor (this is actually the case with the
            //       'CollectionValidationController').
            //
            // Note that we do not handle changes that originated from an descendant
            // because we have already handled them (the caches of all ancestors were
            // cleared when the change was handled on that descendant).

            if (args.ChangeType == ChangeType.ValidationResultChanged)
            {
                bool isChangeOfSelf = !args.ChangedPath.SelectsAncestor();

                if (isChangeOfSelf)
                {
                    InvalidateCache(context);
                    InvalidateParentCachesOf(context.VM);
                }
            }

            this.HandleChangedNext(context, args);
        }
Esempio n. 2
0
 private void NotifyChangeCore(ChangeArgs args)
 {
     CallPropertyChangedHandlerBehaviors(args);
     CallChangeHandlerBehaviors(args);
     ForwardChangeNotificationToParents(args);
     ForwardChangeToViewModel(args);
 }
Esempio n. 3
0
        // If an already invalid child is set or the previous child was invalid,
        // the aggregated validation state of the owner changes, therefore an
        // ValidationResultChanged event should be raised.
        private void DetectValidationResultChange(IBehaviorContext context, Action action)
        {
            IViewModel oldChild = this.GetValueNext <TValue>(context);

            action();

            IViewModel newChild = this.GetValueNext <TValue>(context);

            // It is important to query the 'oldResult' after executing the 'action'. The
            // following scenario could happen otherwise:
            //   1. 'oldResult' is assigned before the action and is valid.
            //   2. The action is executed and makes 'oldChild' invalid and 'newChild'
            //      stays valid. Since 'oldChild' is still in the hierarchy at this
            //      time, the error is propagated to the validation caches of the
            //      parent.
            //   3. 'newResult' is assigned to result of the 'newChild' (valid).
            //   4. We would not detect a change in the 'if' below and therefore not
            //      raise a change which would leave the validation cache of the parents
            //      with the stale error.
            ValidationResult oldResult = GetValidationResultOrValidIfNull(oldChild);
            ValidationResult newResult = GetValidationResultOrValidIfNull(newChild);

            if (!Object.Equals(oldResult, newResult))
            {
                context.NotifyChange(ChangeArgs.ValidationResultChanged());
            }
        }
        public void HandleChange(IBehaviorContext context, ChangeArgs args)
        {
            var c = GetCache(context);

            c.HandleChange(context, args);

            this.HandleChangedNext(context, args);
        }
Esempio n. 5
0
 public void HandleChange(IBehaviorContext context, ChangeArgs args)
 {
     foreach (var depedency in _dependencies)
     {
         depedency.HandleChange(context.VM, args);
     }
     this.HandleChangedNext(context, args);
 }
Esempio n. 6
0
 public override void Execute(
     IViewModel ownerVM,
     ChangeArgs args,
     DeclarativeDependency dependency
     )
 {
     _action((TOwnerVM)ownerVM, args);
 }
Esempio n. 7
0
        public override bool Equals(object obj)
        {
            ChangeArgs other = obj as ChangeArgs;

            return
                (other != null &&
                 other.ChangeType == ChangeType &&
                 other.ChangedVM == ChangedVM &&
                 other.ChangedProperty == ChangedProperty);
        }
        public void HandlePropertyChanged(IBehaviorContext context, ChangeArgs args)
        {
            // Only clear the cache, if the value was successfully set on the next stage
            // (Value for DisplayValue or ValidatedValue for Value).
            if (args.Stage.Sequence > _stage.Sequence)
            {
                _invalidValueCache.Clear(context);
            }

            this.HandlePropertyChangedNext(context, args);
        }
Esempio n. 9
0
 private void ForwardChangeNotificationToParents(ChangeArgs args)
 {
     // Parents have to be cached, because parents may changed by change handlers (declarative dependencies).
     foreach (var parent in Parents.ToArray())
     {
         parent
         .Kernel
         .GetContext()
         .NotifyChange(args);
     }
 }
        public virtual void NotifyPropertyChanged(IBehaviorContext context, ValueStage stage, TValue oldValue, TValue newValue)
        {
            var args = ChangeArgs.PropertyChanged(
                _property, stage,
                reason: null
                );

            context.NotifyChange(args);

            this.NotifyPropertyChangedNext(context, stage, oldValue, newValue);
        }
Esempio n. 11
0
        public void HandleChange(IViewModel ownerVM, ChangeArgs args)
        {
            bool isExpectedChangeType = _changeTypes.Contains(args.ChangeType);

            if (!isExpectedChangeType)
            {
                return;
            }

            PathMatch sourcePathMatch = _sourcePath.Matches(args.ChangedPath);

            if (sourcePathMatch.Success)
            {
                _action.Execute(ownerVM, args, this);
            }
        }
        public void HandlePropertyChanged(IBehaviorContext context, ChangeArgs args)
        {
            AssertInitialized();

            if (_descriptor != null)
            {
                _descriptor.RaiseValueChanged(context.VM);
            }

            IHandlePropertyChangedBehavior next;

            if (TryGetBehavior(out next))
            {
                next.HandlePropertyChanged(context, args);
            }
        }
        public void HandleChange(IBehaviorContext context, CollectionChangedArgs <TItemVM> args)
        {
            var c = args.Collection;

            var oldItems = (IEnumerable <IViewModel>)args.OldItems;
            var newItems = (IEnumerable <IViewModel>)args.NewItems;

            ChangeArgs a;

            switch (args.Type)
            {
            // No change of 'ItemsRemoved' is raised to give the client a chance
            // to distinguish if the removal was due to a repopulation (Type =
            // 'Populated' and 'OldItems' contains items) or if the removal was
            // triggered by a 'Clear', 'Remove' or 'SetItem'.
            case CollectionChangeType.Populated:
                a = ChangeArgs.CollectionPopulated(c, oldItems, args.Reason);
                context.NotifyChange(a);
                break;
            }

            switch (args.Type)
            {
            case CollectionChangeType.ItemRemoved:
            case CollectionChangeType.ItemSet:
            case CollectionChangeType.ItemsCleared:
                if (args.OldItems.Any())
                {
                    a = ChangeArgs.ItemsRemoved(c, oldItems, args.Reason);
                    context.NotifyChange(a);
                }
                break;
            }

            switch (args.Type)
            {
            case CollectionChangeType.ItemAdded:
            case CollectionChangeType.ItemSet:
                a = ChangeArgs.ItemsAdded(c, newItems, args.Reason);
                context.NotifyChange(a);
                break;
            }

            this.HandleChangeNext(context, args);
        }
Esempio n. 14
0
        public void HandleChange(IBehaviorContext context, CollectionChangedArgs <TItemVM> args)
        {
            IEnumerable <TItemVM> changedItems = args
                                                 .OldItems
                                                 .Concat(args.NewItems);

            IEnumerable <ValidationResult> changedItemsResults = changedItems
                                                                 .Select(x => x.Kernel.GetValidationResult());

            var changedItemsResult = ValidationResult.Join(changedItemsResults);

            this.HandleChangeNext(context, args);

            // If already invalid items are added or removed, the aggregated
            // validation state of the collection owner changes, therefore an
            // ValidationResultChanged event should be raised.
            if (!changedItemsResult.IsValid)
            {
                context.NotifyChange(ChangeArgs.ValidationResultChanged(args.Reason));
            }
        }
Esempio n. 15
0
        //internal IList<IPropertySelector> TargetProperties {
        //   get { return _targetProperties; }
        //}

        public override void Execute(
            IViewModel ownerVM,
            ChangeArgs args,
            DeclarativeDependency dependency
            )
        {
            _target.Revalidate(ownerVM);
            //if (TargetPath.IsEmpty) {
            //   RevalidateProperties(ownerVM);
            //} else {
            //   var viewModels = TargetPath.GetDescendants(ownerVM);

            //   foreach (var viewModel in viewModels) {
            //      if (_targetProperties.Count > 0) {
            //         RevalidateProperties(viewModel);
            //      } else {
            //         viewModel.Kernel.Revalidate(ValidationScope.SelfAndLoadedDescendants);
            //      }
            //   }
            //}
        }
Esempio n. 16
0
        private void CallPropertyChangedHandlerBehaviors(ChangeArgs args)
        {
            if (args.ChangeType != ChangeType.PropertyChanged)
            {
                return;
            }

            var result = args
                         .ChangedPath
                         .SelectsOnlyPropertyOf(_vm);

            bool ownPropertyChanged = result.Success;

            if (ownPropertyChanged)
            {
                result
                .Property
                .Behaviors
                .HandlePropertyChangedNext(GetContext(), args);
            }
        }
Esempio n. 17
0
        public void Refresh(IBehaviorContext context, RefreshOptions options)
        {
            RequireInitialized();

            var previousValue = GetValue(context);

            RefreshCache(context);
            var newValue = GetValue(context);

            if (!Object.Equals(newValue, previousValue))
            {
                var args = ChangeArgs.ViewModelPropertyChanged(
                    _property,
                    ValueStage.ValidatedValue,
                    previousValue,
                    newValue,
                    RefreshReason.Create(options.ExecuteRefreshDependencies)
                    );

                context.NotifyChange(args);
            }

            this.RefreshNext(context, options);
        }
Esempio n. 18
0
        public override void InitializeValue(IBehaviorContext context)
        {
            base.InitializeValue(context);

            TValue childVM = this.GetValueNext <TValue>(context);

            if (childVM != null)
            {
                ValidationResult childValidatonResult = childVM
                                                        .Kernel
                                                        .GetValidationResult();

                if (!childValidatonResult.IsValid)
                {
                    // If 'PopulatedWith' returns an already invalid item, the aggregated
                    // validation state of the collection owner changes, therefore an
                    // 'ValidationResultChanged' event should be raised.
                    if (!childValidatonResult.IsValid)
                    {
                        context.NotifyChange(ChangeArgs.ValidationResultChanged());
                    }
                }
            }
        }
 public void HandleChange(IBehaviorContext context, ChangeArgs args)
 {
     _changeHandler((TVM)context.VM, args);
     this.HandleChangedNext(context, args);
 }
            // We eagerly refresh the caches of all ancestors. Consider the case:
            //   (1) A validation result change is notified, thus all caches up the
            //       hierarchy hold invalid validation states.
            //   (2) The next behavior in this chain may access the cached validation
            //       result of an ancestor (this is actually the case with the
            //       'CollectionValidationController').
            //
            // Note that we do not handle changes that originated from an descendant
            // because we have already handled them (the caches of all ancestors were
            // cleared when the change was handled on that descendant).
            public void HandleChange(IBehaviorContext context, ChangeArgs args)
            {
                bool refreshDescendants = false;
                bool resultsChanged     = false;
                var  self = context.VM;

                switch (args.ChangeType)
                {
                case ChangeType.ValidationResultChanged:
                    var ownViewModelResultChanged = args
                                                    .ChangedPath
                                                    .SelectsOnly(self)
                                                    .Success;

                    if (ownViewModelResultChanged)
                    {
                        RefreshViewModelResult(context);
                        resultsChanged = true;
                    }
                    else
                    {
                        var ownPropertyResultChanged = args
                                                       .ChangedPath
                                                       .SelectsOnlyPropertyOf(self)
                                                       .Success;

                        if (ownPropertyResultChanged)
                        {
                            RefreshPropertiesResult(context);
                            resultsChanged = true;
                        }
                    }
                    break;

                case ChangeType.PropertyChanged:
                    var ownViewModelPropertyMayHaveChanged = args
                                                             .ChangedPath
                                                             .SelectsOnlyPropertyOf(self)
                                                             .Success;

                    refreshDescendants = ownViewModelPropertyMayHaveChanged;
                    break;

                case ChangeType.AddedToCollection:
                case ChangeType.RemovedFromCollection:
                    var ownCollectionContentsChanged = args
                                                       .ChangedPath
                                                       .SelectsOnlyCollectionOf(self)
                                                       .Success;

                    refreshDescendants = ownCollectionContentsChanged;
                    break;
                }

                if (refreshDescendants)
                {
                    RefreshChildren(
                        context,
                        removedChildren: args.OldItems,
                        newChildren: args.NewItems
                        );
                }
                else if (resultsChanged)
                {
                    RefreshDerivedResults();
                    NotifyBehaviorOfParent(context);
                }
            }
Esempio n. 21
0
 void IBehaviorContext.NotifyChange(ChangeArgs args)
 {
     Check.NotNull(args, nameof(args));
     NotifyChangeCore(args.PrependViewModel(_vm));
 }
Esempio n. 22
0
 private void ForwardChangeToViewModel(ChangeArgs args)
 {
     _vm.NotifyChange(args);
 }
Esempio n. 23
0
 private void CallChangeHandlerBehaviors(ChangeArgs args)
 {
     _descriptor
     .Behaviors
     .HandleChangedNext(this, args);
 }
Esempio n. 24
0
        //internal IList<IPropertySelector> TargetProperties {
        //   get { return _targetProperties; }
        //}

        public override void Execute(
            IViewModel ownerVM,
            ChangeArgs args,
            DeclarativeDependency dependency
            )
        {
            RefreshReason reason = args.Reason as RefreshReason;

            if (reason != null && !reason.ExecuteRefreshDependencies)
            {
                return;
            }

            RefreshTrace.BeginRefresh(dependency);

            _target.ForeachLoadedDescendant(ownerVM, (vm, props) => {
                if (props.Any())
                {
                    // TODO: The logic with 'wouldRefreshChangeSource' is not correct. The refresh source
                    //       may be an descendant of 'vm' in which case it would nevertheless be refreshed.
                    //       Unit test 'SetValue_WhenValidationResultChanges_WorksWithSelfRecursiveDependency'
                    //       reproduces this.
                    foreach (var prop in props)
                    {
                        bool wouldRefreshChangeSource =
                            vm == args.ChangedVM &&
                            prop == args.ChangedProperty;

                        if (!wouldRefreshChangeSource)
                        {
                            vm.Kernel.RefreshInternal(prop, new RefreshOptions(_executeRefreshDependencies));
                        }
                    }
                }
                else
                {
                    bool wouldRefreshChangeSource = vm == args.ChangedVM;

                    if (!wouldRefreshChangeSource)
                    {
                        vm.Kernel.RefreshInternal(_executeRefreshDependencies);
                    }
                }
            });

            //_target.Refresh(ownerVM, _executeRefreshDependencies);

            //ownerVM.Kernel.RefreshInternal(_target, _executeRefreshDependencies);

            //if (TargetPath.IsEmpty) {
            //   if (_targetProperties.Count > 0) {
            //      RefreshProperties(ownerVM);
            //   } else {
            //      ownerVM.Kernel.RefreshInternal(_executeRefreshDependencies);
            //   }
            //} else {
            //   var viewModels = TargetPath.GetDescendants(ownerVM);

            //   foreach (var viewModel in viewModels) {
            //      if (_targetProperties.Count > 0) {
            //         RefreshProperties(viewModel);
            //      } else {
            //         viewModel.Kernel.RefreshInternal(_executeRefreshDependencies);
            //      }
            //   }
            //}

            RefreshTrace.EndLastRefresh();
        }