Beispiel #1
0
        /// <summary>
        /// Sets the value of the property to the new value.
        /// </summary>
        /// <param name="container">The container of the <see cref="DependencyProperty"/>.</param>
        /// <param name="changeCount">The change count of the current property.</param>
        /// <param name="expression">The <see cref="DependencyExpression"/> which is assigned to the property or null if no expression is assigned.</param>
        /// <param name="baseValue">The base value of the property.</param>
        /// <param name="value">The current value of the property.</param>
        /// <param name="newValue">The new value of the property.</param>
        internal override void SetValue(DependencyObjectContainer container, ref Int16 changeCount, ref GenericEventHandler <IDependencyObject, PropertyChangedEventArgs <TProperty> > changeHandler, ref DependencyExpression expression, ref TProperty baseValue, ref TProperty value, TProperty newValue)
        {
            // Save previous change count, prevents issues when a ThreadAbortException is thrown
            Int16 previousChangeCount = changeCount;

            try
            {
                // Copy previous expression if set
                DependencyExpression oldExpression = expression;

                // Compare the new value with the existing base value to avoid redundant changes to the property value
                if (!Object.Equals(newValue, baseValue))
                {
                    // Increase change count
                    changeCount++;

                    // Get the typed owner
                    TOwner representedObject = (TOwner)container.RepresentedObject;
                    // Copy old value for change events
                    TProperty oldValue = value;


                    // Validate the property value and throw a exception if the value is invalid
                    if (_ValidationCallback?.Invoke(representedObject, newValue) == false)
                    {
                        throw new ArgumentException($"Property value '{newValue}' is invalid for property {OwnerType.Name}.{Name}");
                    }

                    // We can now set the new base value anyway
                    baseValue = newValue;

                    // Coerce value to enable early check for a property change
                    TProperty coercedValue = newValue;
                    // Optional early exit if coercing is enabled and coerced and old value are the same
                    if (_CoerceValueCallback == null || !Object.Equals(coercedValue = _CoerceValueCallback(representedObject, newValue), oldValue))
                    {
                        // Notify that the property owner that the property is changing
                        _ChangingCallback?.Invoke(representedObject, new PropertyChangingEventArgs <TProperty>(changeCount, this, oldValue));

                        // Assign the new value to the property
                        value = coercedValue;

                        // Create a change event args once to avoid unnecessary copies
                        PropertyChangedEventArgs <TProperty> args = new PropertyChangedEventArgs <TProperty>(changeCount, this, coercedValue, oldValue);
                        // Raise the property event when existing
                        _ChangedCallback?.Invoke(representedObject, args);

                        // Only raise the
                        if (changeCount == 1)
                        {
                            // Set the previous change count before raising the events, this prevents
                            changeCount = previousChangeCount;

                            // Raise the event on the property directly
                            changeHandler?.Invoke(representedObject, args);
                            // Raise the event on the owner object
                            container.OnPropertyChange(args);
                        }
                    }
                }

                // It does not matter if the value is different, the expression must be removed in case a value is set
                if (oldExpression != null && expression == oldExpression)
                {
                    // Set expression to null
                    expression = null;
                    // Raise the markup change event
                    container.OnExtensionChange(new PropertyExtensionChangedEventArgs(this, null, oldExpression.ExpressionTemplate));
                }
            }
            finally
            {
                // Set the previous change count
                changeCount = previousChangeCount;
            }
        }
Beispiel #2
0
        /// <summary>
        /// Coerces the current value of the dependency object.
        /// </summary>
        /// <param name="container">The container of the <see cref="DependencyProperty"/>.</param>
        /// <param name="changeCount">The change count of the current property.</param>
        /// <param name="expression">The <see cref="DependencyExpression"/> which is assigned to the property or null if no expression is assigned.</param>
        /// <param name="baseValue">The base value of the property.</param>
        /// <param name="value">The current value of the property.</param>
        internal override void CoerceValue(DependencyObjectContainer container, ref Int16 changeCount, ref GenericEventHandler <IDependencyObject, PropertyChangedEventArgs <TProperty> > changeHandler, DependencyExpression expression, TProperty baseValue, ref TProperty value)
        {
            // Save previous change count, prevents issues when a ThreadAbortException is thrown
            Int16 previousChangeCount = changeCount;

            try
            {
                // Get the typed owner
                TOwner representedObject = (TOwner)container.RepresentedObject;

                // Store previous coerced value
                TProperty oldValue = value;

                // Coerce value to enable early check for a property change
                TProperty coercedValue;

                // Method should only work when we've something to coerce
                if (_CoerceValueCallback != null && !Object.Equals(coercedValue = _CoerceValueCallback(representedObject, baseValue), oldValue))
                {
                    // Increase change count
                    changeCount++;


                    // Notify that the property owner that the property is changing
                    _ChangingCallback?.Invoke(representedObject, new PropertyChangingEventArgs <TProperty>(changeCount, this, oldValue));

                    // Assign the new value to the property
                    value = coercedValue;

                    // Create a change event args once to avoid unnecessary copies
                    PropertyChangedEventArgs <TProperty> args = new PropertyChangedEventArgs <TProperty>(changeCount, this, coercedValue, oldValue);
                    // Raise the property event when existing
                    _ChangedCallback?.Invoke(representedObject, args);

                    // Only raise the
                    if (changeCount == 1)
                    {
                        // Set the previous change count before raising the events, this prevents
                        changeCount = previousChangeCount;

                        // Raise the event on the property directly
                        changeHandler?.Invoke(representedObject, args);
                        // Raise the event on the owner object
                        container.OnPropertyChange(args);
                    }
                }
            }
            finally
            {
                // Set the previous change count
                changeCount = previousChangeCount;
            }
        }
 /// <summary>
 /// Coerces the current value of the dependency object.
 /// </summary>
 /// <param name="container">The container of the <see cref="DependencyProperty"/>.</param>
 /// <param name="changeCount">The change count of the current property.</param>
 /// <param name="expression">The <see cref="DependencyExpression"/> which is assigned to the property or null if no expression is assigned.</param>
 /// <param name="baseValue">The base value of the property.</param>
 /// <param name="value">The current value of the property.</param>
 internal abstract void CoerceValue(DependencyObjectContainer container, ref Int16 changeCount, ref GenericEventHandler <IDependencyObject, PropertyChangedEventArgs <TProperty> > changeHandler, DependencyExpression expression, TProperty baseValue, ref TProperty value);