Skip to content

Avalonia vs WPF

Damian edited this page Jul 15, 2022 · 1 revision

For those of you who are converting a WPF to Avalonia application, here are some helpful hints. The table and samples below were used to convert Prism.WPF to Prism.Avalonia.

Conversion Helpers

[https://docs.avaloniaui.net/misc/wpf/Control-frameworkelement-and-control]

WPF Avalonia Reference
System.Windows Avalonia
System.Windows.FrameworkElement Avalonia.Controls.Control Reference
System.WIndows.FrameworkContentElement Avalonia.Controls.Control
UIElement Avalonia.Controls.Control
ItemsControl.ItemsSource Avalonia.Controls.ItemsControl.ItemsSource Naming Convention
System.Windows.Markup.MarkupExtension Avalonia.Markup.Xaml.MarkupExtension Reference
System.Windows.Markup.ContentPropertyAttribute.ContentProperty Avalonia.Metadata.Content [https://github.com/AvaloniaUI/Avalonia/pull/1126]
System.Windows.Markup Avalonia.Markup.Xaml
System.Windows.Markup.XmlnsDefinition Avalonia.Metadata.XmlnsDefinition
System.Windows.DependencyObject Avalonia.AvaloniaObject
System.Windows.DependencyProperty Avalonia.AvaloniaProperty
System.Windows.DependencyPropertyChangedEventArgs Avalonia.AvaloniaPropertyChangedEventArgs
System.ComponentModel.DesignerProperties.GetIsInDesignMode(DependencyObject element); Avalonia.Controls.Design.IsDesignMode;
System.Windows.Controls.Primitives.Selector ?? used by SelectorRegionAdapter.cs and PrismInitializationExtensions.cs
RoutedEventHandler Not Implemented

AvaloniaProperty vs DependencyProperty

Note, Avalonia places the propertyType as part of TValue in its ..<THost, TValue>(...).

// Avalonia
public static AvaloniaProperty AutoWireViewModelProperty =
    AvaloniaProperty.RegisterAttached<Control, bool>(
        name: "AutoWireViewModel",
        ownerType: typeof(ViewModelLocator),
        defaultValue: false);

// WPF
public static DependencyProperty AutoWireViewModelProperty =
    DependencyProperty.RegisterAttached(
        name: "AutoWireViewModel",
        propertyType: typeof(bool?),
        ownerType: typeof(ViewModelLocator),
        defaultMetaData: new PropertyMetadata(defaultValue: null, propertyChangedCallback: AutoWireViewModelChanged));

Behaviors and Triggers

In order to use Behaviors in Avalonia, you must download the Avalonia XAML Behaviors NuGet.

For example, InvokeCommandActionView.axaml uses InvokeCommandAction.cs.

Inheriting WPF DependencyObject in Avalonia

// WPF:
public partial class ItemMetadata : DependencyObject
{
    ...
    private static void DependencyPropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args)
    {
        ItemMetadata itemMetadata = dependencyObject as ItemMetadata;
        if (itemMetadata != null)
        {
            itemMetadata.InvokeMetadataChanged();
        }
    }

// Avalonia:
public class ItemMetadata : AvaloniaObject
{
    ...
    private static void StyledPropertyChanged(IAvaloniaObject dependencyObject, AvaloniaPropertyChangedEventArgs args)
    {
        ItemMetadata itemMetadata = dependencyObject as ItemMetadata;
        if (itemMetadata != null)
        {
            itemMetadata.InvokeMetadataChanged();
        }
    }

Property

Note

  • Avalonia places WPF's propertyType as part of TValue in <THost, TValue>
  • The THost object type is what is used in the Get and Set methods.
// Avalonia ------------
private static readonly AvaloniaProperty ObservableRegionContextProperty =
    AvaloniaProperty.RegisterAttached<Visual, ObservableObject<object>>(
        name: "ObservableRegionContext",
        ownerType: typeof(RegionContext));

static RegionContext()
{
    ObservableRegionContextProperty.Changed.Subscribe(args => GetObservableContext(args?.Sender as Visual));
}

// WPF -----------------
private static readonly DependencyProperty ObservableRegionContextProperty =
    DependencyProperty.RegisterAttached(
        name: "ObservableRegionContext",
        propertyType: typeof(ObservableObject<object>),
        ownerType: typeof(RegionContext),
        defaultMetadata: null);

Property with Callback

Make sure to include, using System; or else .Subscribe(..) will throw an error.

using System;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Styling;

// Avalonia ------------------
static ClassConstructor()
{
    RegionNameProperty.Changed.Subscribe(args => OnSetRegionNameCallback(args?.Sender, args));
}

public static readonly AvaloniaProperty RegionNameProperty = AvaloniaProperty.RegisterAttached<AvaloniaObject, string>(
    name: "RegionName",
    ownerType: typeof(RegionManager));

// WPF -----------------------
public static readonly DependencyProperty RegionNameProperty = DependencyProperty.RegisterAttached(
    name: "RegionName",
    propertyType: typeof(string),
    ownerType: typeof(RegionManager),
    defaultMetadata: new PropertyMetadata(defaultValue: null, propertyChangedCallback: OnSetRegionNameCallback));