using System; using Avalonia.Data; using Avalonia.Reactive; #nullable enable namespace Avalonia { /// /// Base class for direct properties. /// /// The type of the property's value. /// /// Whereas is typed on the owner type, this base /// class provides a non-owner-typed interface to a direct poperty. /// public abstract class DirectPropertyBase : AvaloniaProperty { /// /// Initializes a new instance of the class. /// /// The name of the property. /// The type of the class that registers the property. /// The property metadata. /// /// Whether the property is interested in data validation. /// protected DirectPropertyBase( string name, Type ownerType, PropertyMetadata metadata, bool enableDataValidation) : base(name, ownerType, metadata) { IsDataValidationEnabled = enableDataValidation; } /// /// Initializes a new instance of the class. /// /// The property to copy. /// The new owner type. /// Optional overridden metadata. /// /// Whether the property is interested in data validation. /// protected DirectPropertyBase( AvaloniaProperty source, Type ownerType, PropertyMetadata metadata, bool enableDataValidation) : base(source, ownerType, metadata) { IsDataValidationEnabled = enableDataValidation; } /// /// Gets the type that registered the property. /// public abstract Type Owner { get; } /// /// Gets a value that indicates whether data validation is enabled for the property. /// public bool IsDataValidationEnabled { get; } /// /// Gets the value of the property on the instance. /// /// The instance. /// The property value. internal abstract TValue InvokeGetter(IAvaloniaObject instance); /// /// Sets the value of the property on the instance. /// /// The instance. /// The value. internal abstract void InvokeSetter(IAvaloniaObject instance, BindingValue value); /// /// Gets the unset value for the property on the specified type. /// /// The type. /// The unset value. public TValue GetUnsetValue(Type type) { type = type ?? throw new ArgumentNullException(nameof(type)); return GetMetadata(type).UnsetValue; } /// /// Gets the property metadata for the specified type. /// /// The type. /// /// The property metadata. /// public new DirectPropertyMetadata GetMetadata(Type type) { return (DirectPropertyMetadata)base.GetMetadata(type); } /// internal override void NotifyInitialized(IAvaloniaObject o) { if (HasNotifyInitializedObservers) { var e = new AvaloniaPropertyChangedEventArgs( o, this, default, InvokeGetter(o), BindingPriority.Unset); NotifyInitialized(e); } } /// internal override void RouteClearValue(IAvaloniaObject o) { o.ClearValue(this); } /// internal override object? RouteGetValue(IAvaloniaObject o) { return o.GetValue(this); } /// internal override void RouteSetValue( IAvaloniaObject o, object value, BindingPriority priority) { var v = TryConvert(value); if (v.HasValue) { o.SetValue(this, (TValue)v.Value); } else if (v.Type == BindingValueType.UnsetValue) { o.ClearValue(this); } else if (v.HasError) { throw v.Error!; } } /// internal override IDisposable RouteBind( IAvaloniaObject o, IObservable> source, BindingPriority priority) { var adapter = TypedBindingAdapter.Create(o, this, source); return o.Bind(this, adapter); } internal override void RouteInheritanceParentChanged(AvaloniaObject o, IAvaloniaObject oldParent) { throw new NotSupportedException("Direct properties do not support inheritance."); } } }