/// <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="value">The current value of the property.</param> /// <param name="newValue">The new value of the property.</param> internal override void SetMarkupValue(DependencyObjectContainer container, ref Int16 changeCount, ref GenericEventHandler <IDependencyObject, PropertyChangedEventArgs <TProperty> > changeHandler, ref TProperty value, TProperty newValue) { // Save previous change count, prevents issues when a ThreadAbortException is thrown Int16 previousChangeCount = changeCount; try { // 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}"); } // 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); } } } 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 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> /// 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; } }