using System; using Avalonia.Data; using Avalonia.PropertyStore; 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 property. /// 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. protected DirectPropertyBase( string name, Type ownerType, AvaloniaPropertyMetadata metadata) : base(name, ownerType, metadata) { Owner = ownerType; } /// /// Initializes a new instance of the class. /// /// The property to copy. /// The new owner type. /// Optional overridden metadata. protected DirectPropertyBase( DirectPropertyBase source, Type ownerType, AvaloniaPropertyMetadata metadata) : base(source, ownerType, metadata) { Owner = ownerType; } /// /// Gets the type that registered the property. /// public Type Owner { get; } /// /// Gets the value of the property on the instance. /// /// The instance. /// The property value. internal abstract TValue InvokeGetter(AvaloniaObject instance); /// /// Sets the value of the property on the instance. /// /// The instance. /// The value. internal abstract void InvokeSetter(AvaloniaObject 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); } /// /// Overrides the metadata for the property on the specified type. /// /// The type. /// The metadata. public void OverrideMetadata(DirectPropertyMetadata metadata) where T : AvaloniaObject { base.OverrideMetadata(typeof(T), metadata); } /// /// Overrides the metadata for the property on the specified type. /// /// The type. /// The metadata. public void OverrideMetadata(Type type, DirectPropertyMetadata metadata) { base.OverrideMetadata(type, metadata); } internal override EffectiveValue CreateEffectiveValue(AvaloniaObject o) { throw new InvalidOperationException("Cannot create EffectiveValue for direct property."); } /// internal override void RouteClearValue(AvaloniaObject o) { o.ClearValue(this); } /// internal override object? RouteGetValue(AvaloniaObject o) { return o.GetValue(this); } internal override object? RouteGetBaseValue(AvaloniaObject o) { return o.GetValue(this); } /// internal override IDisposable? RouteSetValue( AvaloniaObject 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!; } return null; } internal override void RouteSetCurrentValue(AvaloniaObject o, object? value) { RouteSetValue(o, value, BindingPriority.LocalValue); } /// /// Routes an untyped Bind call to a typed call. /// /// The object instance. /// The binding source. /// The priority. internal override IDisposable RouteBind( AvaloniaObject o, IObservable source, BindingPriority priority) { return o.Bind(this, source); } } }