public TValue GetValue(IBehaviorContext context)
        {
            RequireInitialized();

            if (!_cache.HasValue(context))
            {
                if (_isProviding.GetWithDefault(context, false))
                {
                    // This check is important to avoid the following endless recursion:
                    //   1. GetValue calls ProvideValue
                    //   2. ProvideValue directly or indirectly calls GetValue
                    //   3. GetValue calls Provide value because the cache is not set yet.
                    //   4. ProvideValue calls GetValue again
                    //
                    // The alternative would be to return default(TValue) but it is better
                    // to avoid this situation altogehter.
                    throw new InvalidOperationException(EViewModels.ValueAccessedWithinProvideValue);
                }

                _isProviding.Set(context, true);
                TValue value = ProvideValue(context);
                _cache.Set(context, value);
                _isProviding.Clear(context);

                OnInitialize(context);
            }

            return(_cache.Get(context));
        }
        public void Refresh(IBehaviorContext context, RefreshOptions options)
        {
            // Call next behavior first, because a source accessor behavior may handle
            // it.
            this.RefreshNext(context, options);
            _collectionSourceCache.Clear(context);

            // ToArray so that (1) source is only enumerated once and (2) acess by index
            // (required by the equality check) is guaranteed to be fast.
            TItemSource[]           newSourceItems = GetSourceItems(context).ToArray();
            IVMCollection <TItemVM> vmCollection   = GetValue(context);

            IEnumerable <TItemVM> itemsToRefresh = Enumerable.Empty <TItemVM>();

            if (AreCollectionContentsEqual(vmCollection, newSourceItems))
            {
                itemsToRefresh = vmCollection;
            }
            else
            {
                Dictionary <TItemSource, TItemVM> previousItemsBySource = vmCollection.ToDictionary(
                    x => x.Source,
                    _reusabilitySourceComparer
                    );

                List <TItemVM> newItems    = new List <TItemVM>();
                List <TItemVM> reusedItems = new List <TItemVM>();

                foreach (TItemSource s in newSourceItems)
                {
                    TItemVM item;
                    bool    isReusedItem = previousItemsBySource.TryGetValue(s, out item);

                    if (isReusedItem)
                    {
                        reusedItems.Add(item);
                    }
                    else
                    {
                        item = CreateAndInitializeItem(context, s);
                    }

                    newItems.Add(item);
                }

                vmCollection.ReplaceItems(newItems, RefreshReason.Create(options.ExecuteRefreshDependencies));
                itemsToRefresh = reusedItems;
            }

            if (options.Scope.HasFlag(RefreshScope.Content))
            {
                itemsToRefresh
                .ForEach(x => x.Kernel.RefreshWithoutValidation(options.ExecuteRefreshDependencies));
            }
        }
        public void Revalidate(IBehaviorContext context)
        {
            ValidationController controller = _validationController.Get(context);
            var validationResult            = controller.GetResult(_step, context.VM, _property);

            bool valueWasInvalid          = _invalidValueCache.HasValue(context);
            bool valueIsNotInvalidAnymore = validationResult.IsValid;

            if (valueWasInvalid && valueIsNotInvalidAnymore)
            {
                TValue previouslyInvalidValue = _invalidValueCache.Get(context);

                _invalidValueCache.Clear(context);
                SetValueNext(context, previouslyInvalidValue);
            }
            else
            {
                this.PropertyRevalidateNext(context);
            }

            _resultManager.UpdateValidationResult(context, validationResult);
        }
 protected void RefreshCache(IBehaviorContext context)
 {
     _cache.Clear(context);
     GetValue(context);
 }
 public void EndValidation(IBehaviorContext context)
 {
     _validationController.Clear(context);
     this.EndValidationNext(context);
 }