Skip to main content
The AvaloniaObject class is the base class for all objects that support Avalonia’s property system. It is analogous to DependencyObject in WPF and provides the infrastructure for styled properties, data binding, property inheritance, and change notification.

Overview

The AvaloniaObject provides:
  • Property system with styled and direct properties
  • Data binding support
  • Property value inheritance
  • Change notification via INotifyPropertyChanged
  • Property coercion and validation
  • Animation support
  • Thread affinity (dispatcher-bound)

Namespace

Avalonia

Inheritance

AvaloniaObject (base class for most Avalonia UI elements)

Key Concepts

Property Types

Avalonia supports two types of properties:
  1. Styled Properties - Properties that support styling, binding, inheritance, and animations
  2. Direct Properties - Lightweight properties that wrap standard CLR properties

Properties

Dispatcher
Dispatcher
Gets the Dispatcher that this AvaloniaObject is associated with. All property operations must occur on this dispatcher’s thread.
InheritanceParent
AvaloniaObject?
Gets or sets the parent object from which inherited property values are obtained. This is typically the logical or visual parent in the tree.

Methods

GetValue

public object? GetValue(AvaloniaProperty property)
public T GetValue<T>(StyledProperty<T> property)
public T GetValue<T>(DirectPropertyBase<T> property)
Gets the current value of an AvaloniaProperty.
property
AvaloniaProperty
required
The property to get the value for.
Returns: The current effective value of the property. Example:
var width = control.GetValue(WidthProperty);
var background = control.GetValue(BackgroundProperty);

SetValue

public IDisposable? SetValue(
    AvaloniaProperty property,
    object? value,
    BindingPriority priority = BindingPriority.LocalValue)

public IDisposable? SetValue<T>(
    StyledProperty<T> property,
    T value,
    BindingPriority priority = BindingPriority.LocalValue)

public void SetValue<T>(DirectPropertyBase<T> property, T value)
Sets the value of an AvaloniaProperty.
property
AvaloniaProperty
required
The property to set.
value
T
required
The new value.
priority
BindingPriority
The priority of the value. Default is LocalValue. Higher priority values take precedence.
Returns: For styled properties, an IDisposable that can be used to revert the value; null otherwise. Example:
control.SetValue(WidthProperty, 100);
control.SetValue(BackgroundProperty, Brushes.Red);

// Setting with priority
var subscription = control.SetValue(OpacityProperty, 0.5, BindingPriority.Animation);
// Later: subscription.Dispose(); // Reverts the value

SetCurrentValue

public void SetCurrentValue(AvaloniaProperty property, object? value)
public void SetCurrentValue<T>(StyledProperty<T> property, T value)
Sets the value of a property without changing its value source. The new value will have the property’s current binding priority, and existing bindings will continue to work.
property
AvaloniaProperty
required
The property to set.
value
T
required
The new value.
Example:
// Even if Width is bound, this sets the current value without breaking the binding
control.SetCurrentValue(WidthProperty, 200);

ClearValue

public void ClearValue(AvaloniaProperty property)
public void ClearValue<T>(AvaloniaProperty<T> property)
public void ClearValue<T>(StyledProperty<T> property)
public void ClearValue<T>(DirectPropertyBase<T> property)
Clears the local value of a property, reverting it to its default or inherited value.
property
AvaloniaProperty
required
The property to clear.
Example:
control.SetValue(WidthProperty, 100);
control.ClearValue(WidthProperty); // Width reverts to default or inherited value

Bind

public IDisposable Bind(
    AvaloniaProperty property,
    IObservable<object?> source,
    BindingPriority priority = BindingPriority.LocalValue)

public IDisposable Bind<T>(
    StyledProperty<T> property,
    IObservable<T> source,
    BindingPriority priority = BindingPriority.LocalValue)

public BindingExpressionBase Bind(AvaloniaProperty property, BindingBase binding)
Binds a property to an observable or binding expression.
property
AvaloniaProperty
required
The property to bind.
source
IObservable<T>
required
The observable source that provides values.
priority
BindingPriority
The priority of the binding.
Returns: An IDisposable that can be used to terminate the binding. Example:
// Bind to an observable
var subscription = control.Bind(WidthProperty, viewModel.WhenAnyValue(x => x.Width));

// Bind using a Binding object
control.Bind(TextBlock.TextProperty, new Binding("Name"));

// Later: subscription.Dispose(); // Removes the binding

GetBaseValue

public Optional<T> GetBaseValue<T>(StyledProperty<T> property)
Gets the base value of a styled property, excluding animated values.
property
StyledProperty<T>
required
The property to query.
Returns: The base value if set; otherwise, Optional<T>.Empty. Note: This method does not return inherited or default values, only explicitly set values.

IsSet

public bool IsSet(AvaloniaProperty property)
Checks whether a property has a local value assigned or a binding targeting it.
property
AvaloniaProperty
required
The property to check.
Returns: true if the property is set; otherwise, false. Example:
if (control.IsSet(WidthProperty))
{
    // Width has been explicitly set
}

IsAnimating

public bool IsAnimating(AvaloniaProperty property)
Checks whether a property is currently being animated.
property
AvaloniaProperty
required
The property to check.
Returns: true if the property is animating; otherwise, false.

CoerceValue

public void CoerceValue(AvaloniaProperty property)
Forces coercion of the specified property value using its registered coercion callback.
property
AvaloniaProperty
required
The property to coerce.

CheckAccess

public bool CheckAccess()
Checks whether the current thread is the UI thread associated with this object. Returns: true if the current thread is the UI thread; otherwise, false.

VerifyAccess

public void VerifyAccess()
Throws an exception if the current thread is not the UI thread associated with this object. Throws: InvalidOperationException if called from the wrong thread.

Protected Methods

OnPropertyChanged

protected virtual void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
Called when an Avalonia property value changes on this object. Override this method to respond to property changes.
change
AvaloniaPropertyChangedEventArgs
required
Details about the property change, including old and new values.
Example:
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
    base.OnPropertyChanged(change);
    
    if (change.Property == WidthProperty)
    {
        // Respond to width changes
        InvalidateMeasure();
    }
}

SetAndRaise

protected bool SetAndRaise<T>(DirectPropertyBase<T> property, ref T field, T value)
Sets the backing field for a direct property and raises the PropertyChanged event if the value has changed.
property
DirectPropertyBase<T>
required
The property being set.
field
T
required
Reference to the backing field.
value
T
required
The new value.
Returns: true if the value changed; otherwise, false. Example:
private string? _name;
public static readonly DirectProperty<MyControl, string?> NameProperty =
    AvaloniaProperty.RegisterDirect<MyControl, string?>(
        nameof(Name),
        o => o.Name,
        (o, v) => o.Name = v);

public string? Name
{
    get => _name;
    set => SetAndRaise(NameProperty, ref _name, value);
}

RaisePropertyChanged

protected void RaisePropertyChanged<T>(
    DirectPropertyBase<T> property,
    T oldValue,
    T newValue)
Manually raises the PropertyChanged event for a direct property.
property
DirectPropertyBase<T>
required
The property that changed.
oldValue
T
required
The old value.
newValue
T
required
The new value.

Events

PropertyChanged
EventHandler<AvaloniaPropertyChangedEventArgs>?
Raised when an AvaloniaProperty value changes on this object.
control.PropertyChanged += (sender, e) =>
{
    if (e.Property == WidthProperty)
    {
        Console.WriteLine($"Width changed from {e.OldValue} to {e.NewValue}");
    }
};

Indexer

public object? this[AvaloniaProperty property] { get; set; }
Gets or sets the value of a property using indexer syntax. Example:
// Get value
var width = control[WidthProperty];

// Set value
control[WidthProperty] = 100;

Usage Examples

Basic Property Usage

public class MyControl : AvaloniaObject
{
    // Define a styled property
    public static readonly StyledProperty<string?> TitleProperty =
        AvaloniaProperty.Register<MyControl, string?>(nameof(Title), "Default Title");

    // CLR property wrapper
    public string? Title
    {
        get => GetValue(TitleProperty);
        set => SetValue(TitleProperty, value);
    }
}

// Usage
var control = new MyControl();
control.Title = "Hello World";
var title = control.Title;

Direct Property

public class MyControl : AvaloniaObject
{
    private string? _name;
    
    public static readonly DirectProperty<MyControl, string?> NameProperty =
        AvaloniaProperty.RegisterDirect<MyControl, string?>(
            nameof(Name),
            o => o.Name,
            (o, v) => o.Name = v);

    public string? Name
    {
        get => _name;
        set => SetAndRaise(NameProperty, ref _name, value);
    }
}

Property Change Notification

public class MyControl : Control
{
    protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
    {
        base.OnPropertyChanged(change);
        
        if (change.Property == BoundsProperty)
        {
            // Respond to bounds changes
            Console.WriteLine($"Bounds changed to {Bounds}");
        }
    }
}

Data Binding

// Bind to a view model property
var binding = new Binding("UserName") 
{ 
    Source = viewModel 
};
textBlock.Bind(TextBlock.TextProperty, binding);

// Bind to an observable
var subscription = textBlock.Bind(
    TextBlock.TextProperty,
    viewModel.WhenAnyValue(x => x.UserName)
);

Property Priorities

// Set local value (highest user priority)
control.SetValue(OpacityProperty, 0.5);

// Set animated value (overrides local value)
var animation = control.SetValue(OpacityProperty, 1.0, BindingPriority.Animation);

// Animation value is active
Console.WriteLine(control.Opacity); // 1.0

// Remove animation
animation.Dispose();

// Local value is now active
Console.WriteLine(control.Opacity); // 0.5

Thread Safety

All AvaloniaObject instances are bound to the UI thread (dispatcher) on which they were created. Property operations must occur on this thread. Use CheckAccess() to verify thread access and VerifyAccess() to enforce it.
if (!control.CheckAccess())
{
    // Marshal to UI thread
    control.Dispatcher.InvokeAsync(() =>
    {
        control.Width = 100;
    });
}
else
{
    control.Width = 100;
}

See Also

Build docs developers (and LLMs) love