Suspension context that can track properties during a suspension period.
Ejemplo n.º 1
0
        // ReSharper restore RedundantOverridenMember

        /// <summary>
        /// Suspends the change callbacks whenever a property has been called. This is very useful when
        /// there are expensive property change callbacks registered with a property that need to be
        /// temporarily disabled.
        /// </summary>
        /// <returns></returns>
        public IDisposable SuspendChangeCallbacks()
        {
            var token = new DisposableToken <ModelBase>(this, x =>
            {
                lock (_lock)
                {
                    if (_changeCallbacksSuspensionContext is null)
                    {
                        _changeCallbacksSuspensionContext = new SuspensionContext();
                    }

                    _changeCallbacksSuspensionContext.Increment();
                }
            },
                                                        x =>
            {
                lock (_lock)
                {
                    var suspensionContext = _changeCallbacksSuspensionContext;
                    if (suspensionContext != null)
                    {
                        suspensionContext.Decrement();

                        if (suspensionContext.Counter == 0)
                        {
                            _changeCallbacksSuspensionContext = null;
                        }
                    }
                }

                // Note: don't invoke the "missed" callbacks
            });

            return(token);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Suspends the validation until the disposable token has been disposed.
        /// </summary>
        /// <returns></returns>
        public IDisposable SuspendValidations(bool validateOnResume = true)
        {
            var token = new DisposableToken <ModelBase>(this, x =>
            {
                lock (_lock)
                {
                    if (_validationSuspensionContext == null)
                    {
                        _validationSuspensionContext = new SuspensionContext();
                    }

                    _validationSuspensionContext.Increment();
                }
            },
                                                        x =>
            {
                SuspensionContext suspensionContext;

                lock (_lock)
                {
                    suspensionContext = _validationSuspensionContext;
                    if (suspensionContext != null)
                    {
                        suspensionContext.Decrement();

                        if (suspensionContext.Counter == 0)
                        {
                            _validationSuspensionContext = null;
                        }
                    }
                }

                if (suspensionContext != null && suspensionContext.Counter == 0)
                {
                    if (!validateOnResume)
                    {
                        // Only catch up what we missed
                        var properties = suspensionContext.Properties;

                        foreach (var property in properties)
                        {
                            ValidatePropertyUsingAnnotations(property);
                        }
                    }
                    else
                    {
                        // We need to force validation on attributes again with this flag
                        Validate(true, true);
                    }
                }
            });

            return(token);
        }
Ejemplo n.º 3
0
        public void CorrectlyAddsProperties()
        {
            var suspensionContext = new SuspensionContext();
            
            suspensionContext.Add(null);
            suspensionContext.Add("A");
            suspensionContext.Add("B");

            var items = suspensionContext.Properties.ToList();

            Assert.AreEqual(string.Empty, items[0]);
            Assert.AreEqual("A", items[1]);
            Assert.AreEqual("B", items[2]);
        }
Ejemplo n.º 4
0
        public void PreventsDuplicates()
        {
            var suspensionContext = new SuspensionContext();

            suspensionContext.Add(null);
            suspensionContext.Add(string.Empty);
            suspensionContext.Add("A");
            suspensionContext.Add("A");

            var items = suspensionContext.Properties.ToList();

            Assert.AreEqual(2, items.Count);
            Assert.AreEqual(string.Empty, items[0]);
            Assert.AreEqual("A", items[1]);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Suspends the change notifications until the disposed object has been released.
        /// </summary>
        /// <param name="raiseOnResume">if set to <c>true</c>, the notifications are invoked on resume.</param>
        /// <returns>A disposable object.</returns>
        public IDisposable SuspendChangeNotifications(bool raiseOnResume = true)
        {
            var token = new DisposableToken <ModelBase>(this, x =>
            {
                lock (_lock)
                {
                    if (_changeNotificationsSuspensionContext is null)
                    {
                        _changeNotificationsSuspensionContext = new SuspensionContext();
                    }

                    _changeNotificationsSuspensionContext.Increment();
                }
            },
                                                        x =>
            {
                SuspensionContext suspensionContext;

                lock (_lock)
                {
                    suspensionContext = _changeNotificationsSuspensionContext;
                    if (suspensionContext != null)
                    {
                        suspensionContext.Decrement();

                        if (suspensionContext.Counter == 0)
                        {
                            _changeNotificationsSuspensionContext = null;
                        }
                    }
                }

                if (raiseOnResume)
                {
                    if (suspensionContext != null && suspensionContext.Counter == 0)
                    {
                        var properties = suspensionContext.Properties;

                        foreach (var property in properties)
                        {
                            RaisePropertyChanged(property);
                        }
                    }
                }
            });

            return(token);
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Suspends the validation until the disposable token has been disposed.
        /// </summary>
        /// <returns></returns>
        public IDisposable SuspendValidations(bool validateOnResume = true)
        {
            var token = new DisposableToken<ModelBase>(this, x =>
            {
                lock (_validationLock)
                {
                    if (_validationSuspensionContext == null)
                    {
                        _validationSuspensionContext = new SuspensionContext();
                    }

                    _validationSuspensionContext.Increment();
                }
            },
            x =>
            {
                SuspensionContext suspensionContext;

                lock (_validationLock)
                {
                    suspensionContext = _validationSuspensionContext;
                    if (suspensionContext != null)
                    {
                        suspensionContext.Decrement();

                        if (suspensionContext.Counter == 0)
                        {
                            _validationSuspensionContext = null;
                        }
                    }
                }

                if (validateOnResume)
                {
                    if (suspensionContext != null && suspensionContext.Counter == 0)
                    {
                        //var properties = suspensionContext.Properties;

                        // TODO: In v5, replace with context and smart validation
                        Validate(true, true);

                        //foreach (var property in properties)
                        //{
                        //    Validate(property);
                        //}
                    }
                }
            });

            return token;
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Suspends the change notifications until the disposed object has been released.
        /// </summary>
        /// <param name="raiseOnResume">if set to <c>true</c>, the notifications are invoked on resume.</param>
        /// <returns>A disposable object.</returns>
        public IDisposable SuspendChangeNotifications(bool raiseOnResume = true)
        {
            var token = new DisposableToken<ModelBase>(this, x =>
            {
                lock (_propertyValuesLock)
                {
                    if (_changeNotificationsSuspensionContext == null)
                    {
                        _changeNotificationsSuspensionContext = new SuspensionContext();
                    }

                    _changeNotificationsSuspensionContext.Increment();
                }
            },
            x =>
            {
                SuspensionContext suspensionContext;

                lock (_propertyValuesLock)
                {
                    suspensionContext = _changeNotificationsSuspensionContext;
                    if (suspensionContext != null)
                    {
                        suspensionContext.Decrement();

                        if (suspensionContext.Counter == 0)
                        {
                            _changeNotificationsSuspensionContext = null;
                        }
                    }
                }

                if (raiseOnResume)
                {
                    if (suspensionContext != null && suspensionContext.Counter == 0)
                    {
                        var properties = suspensionContext.Properties;

                        foreach (var property in properties)
                        {
                            RaisePropertyChanged(property);
                        }
                    }
                }
            });

            return token;
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Suspends the change callbacks whenever a property has been called. This is very useful when
        /// there are expensive property change callbacks registered with a property that need to be
        /// temporarily disabled.
        /// </summary>
        /// <returns></returns>
        public IDisposable SuspendChangeCallbacks()
        {
            var token = new DisposableToken<ModelBase>(this, x =>
            {
                lock (_propertyValuesLock)
                {
                    if (_changeCallbacksSuspensionContext == null)
                    {
                        _changeCallbacksSuspensionContext = new SuspensionContext();
                    }

                    _changeCallbacksSuspensionContext.Increment();
                }
            },
            x =>
            {
                lock (_propertyValuesLock)
                {
                    var suspensionContext = _changeCallbacksSuspensionContext;
                    if (suspensionContext != null)
                    {
                        suspensionContext.Decrement();

                        if (suspensionContext.Counter == 0)
                        {
                            _changeCallbacksSuspensionContext = null;
                        }
                    }
                }

                // Note: don't invoke the "missed" callbacks
            });

            return token;
        }