|
|
@@ -22,27 +22,11 @@ namespace Avalonia
|
|
|
/// </remarks>
|
|
|
public class AvaloniaObject : IAvaloniaObject, IAvaloniaObjectDebug, INotifyPropertyChanged
|
|
|
{
|
|
|
- /// <summary>
|
|
|
- /// The parent object that inherited values are inherited from.
|
|
|
- /// </summary>
|
|
|
private IAvaloniaObject _inheritanceParent;
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// Maintains a list of direct property binding subscriptions so that the binding source
|
|
|
- /// doesn't get collected.
|
|
|
- /// </summary>
|
|
|
private List<DirectBindingSubscription> _directBindings;
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// Event handler for <see cref="INotifyPropertyChanged"/> implementation.
|
|
|
- /// </summary>
|
|
|
private PropertyChangedEventHandler _inpcChanged;
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// Event handler for <see cref="PropertyChanged"/> implementation.
|
|
|
- /// </summary>
|
|
|
private EventHandler<AvaloniaPropertyChangedEventArgs> _propertyChanged;
|
|
|
-
|
|
|
+ private EventHandler<AvaloniaPropertyChangedEventArgs> _inheritablePropertyChanged;
|
|
|
private ValueStore _values;
|
|
|
private ValueStore Values => _values ?? (_values = new ValueStore(this));
|
|
|
|
|
|
@@ -52,32 +36,7 @@ namespace Avalonia
|
|
|
public AvaloniaObject()
|
|
|
{
|
|
|
VerifyAccess();
|
|
|
-
|
|
|
- void Notify(AvaloniaProperty property)
|
|
|
- {
|
|
|
- object value = property.IsDirect ?
|
|
|
- ((IDirectPropertyAccessor)property).GetValue(this) :
|
|
|
- ((IStyledPropertyAccessor)property).GetDefaultValue(GetType());
|
|
|
-
|
|
|
- var e = new AvaloniaPropertyChangedEventArgs(
|
|
|
- this,
|
|
|
- property,
|
|
|
- AvaloniaProperty.UnsetValue,
|
|
|
- value,
|
|
|
- BindingPriority.Unset);
|
|
|
-
|
|
|
- property.NotifyInitialized(e);
|
|
|
- }
|
|
|
-
|
|
|
- foreach (var property in AvaloniaPropertyRegistry.Instance.GetRegistered(this))
|
|
|
- {
|
|
|
- Notify(property);
|
|
|
- }
|
|
|
-
|
|
|
- foreach (var property in AvaloniaPropertyRegistry.Instance.GetRegisteredAttached(this.GetType()))
|
|
|
- {
|
|
|
- Notify(property);
|
|
|
- }
|
|
|
+ AvaloniaPropertyRegistry.Instance.NotifyInitialized(this);
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
@@ -98,6 +57,15 @@ namespace Avalonia
|
|
|
remove { _inpcChanged -= value; }
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Raised when an inheritable <see cref="AvaloniaProperty"/> value changes on this object.
|
|
|
+ /// </summary>
|
|
|
+ event EventHandler<AvaloniaPropertyChangedEventArgs> IAvaloniaObject.InheritablePropertyChanged
|
|
|
+ {
|
|
|
+ add { _inheritablePropertyChanged += value; }
|
|
|
+ remove { _inheritablePropertyChanged -= value; }
|
|
|
+ }
|
|
|
+
|
|
|
/// <summary>
|
|
|
/// Gets or sets the parent object that inherited <see cref="AvaloniaProperty"/> values
|
|
|
/// are inherited from.
|
|
|
@@ -118,8 +86,9 @@ namespace Avalonia
|
|
|
{
|
|
|
if (_inheritanceParent != null)
|
|
|
{
|
|
|
- _inheritanceParent.PropertyChanged -= ParentPropertyChanged;
|
|
|
+ _inheritanceParent.InheritablePropertyChanged -= ParentPropertyChanged;
|
|
|
}
|
|
|
+
|
|
|
var properties = AvaloniaPropertyRegistry.Instance.GetRegistered(this)
|
|
|
.Concat(AvaloniaPropertyRegistry.Instance.GetRegisteredAttached(this.GetType()));
|
|
|
var inherited = (from property in properties
|
|
|
@@ -144,7 +113,7 @@ namespace Avalonia
|
|
|
|
|
|
if (_inheritanceParent != null)
|
|
|
{
|
|
|
- _inheritanceParent.PropertyChanged += ParentPropertyChanged;
|
|
|
+ _inheritanceParent.InheritablePropertyChanged += ParentPropertyChanged;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -421,6 +390,7 @@ namespace Avalonia
|
|
|
|
|
|
internal void BindingNotificationReceived(AvaloniaProperty property, BindingNotification notification)
|
|
|
{
|
|
|
+ LogIfError(property, notification);
|
|
|
UpdateDataValidation(property, notification);
|
|
|
}
|
|
|
|
|
|
@@ -452,6 +422,23 @@ namespace Avalonia
|
|
|
});
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Logs a binding error for a property.
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="property">The property that the error occurred on.</param>
|
|
|
+ /// <param name="e">The binding error.</param>
|
|
|
+ protected internal virtual void LogBindingError(AvaloniaProperty property, Exception e)
|
|
|
+ {
|
|
|
+ Logger.Log(
|
|
|
+ LogEventLevel.Warning,
|
|
|
+ LogArea.Binding,
|
|
|
+ this,
|
|
|
+ "Error in binding to {Target}.{Property}: {Message}",
|
|
|
+ this,
|
|
|
+ property,
|
|
|
+ e.Message);
|
|
|
+ }
|
|
|
+
|
|
|
/// <summary>
|
|
|
/// Called to update the validation state for properties for which data validation is
|
|
|
/// enabled.
|
|
|
@@ -509,6 +496,11 @@ namespace Avalonia
|
|
|
PropertyChangedEventArgs e2 = new PropertyChangedEventArgs(property.Name);
|
|
|
_inpcChanged(this, e2);
|
|
|
}
|
|
|
+
|
|
|
+ if (property.Inherits)
|
|
|
+ {
|
|
|
+ _inheritablePropertyChanged?.Invoke(this, e);
|
|
|
+ }
|
|
|
}
|
|
|
finally
|
|
|
{
|
|
|
@@ -628,7 +620,7 @@ namespace Avalonia
|
|
|
/// </summary>
|
|
|
/// <param name="property">The property.</param>
|
|
|
/// <returns>The default value.</returns>
|
|
|
- internal object GetDefaultValue(AvaloniaProperty property)
|
|
|
+ private object GetDefaultValue(AvaloniaProperty property)
|
|
|
{
|
|
|
if (property.Inherits && InheritanceParent is AvaloniaObject aobj)
|
|
|
return aobj.GetValue(property);
|
|
|
@@ -648,7 +640,7 @@ namespace Avalonia
|
|
|
|
|
|
if (notification != null)
|
|
|
{
|
|
|
- notification.LogIfError(this, property);
|
|
|
+ LogIfError(property, notification);
|
|
|
value = notification.Value;
|
|
|
}
|
|
|
|
|
|
@@ -780,6 +772,29 @@ namespace Avalonia
|
|
|
return description?.Description ?? o.ToString();
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Logs a mesage if the notification represents a binding error.
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="property">The property being bound.</param>
|
|
|
+ /// <param name="notification">The binding notification.</param>
|
|
|
+ private void LogIfError(AvaloniaProperty property, BindingNotification notification)
|
|
|
+ {
|
|
|
+ if (notification.ErrorType == BindingErrorType.Error)
|
|
|
+ {
|
|
|
+ if (notification.Error is AggregateException aggregate)
|
|
|
+ {
|
|
|
+ foreach (var inner in aggregate.InnerExceptions)
|
|
|
+ {
|
|
|
+ LogBindingError(property, inner);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ LogBindingError(property, notification.Error);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
/// <summary>
|
|
|
/// Logs a property set message.
|
|
|
/// </summary>
|