This lane extends the skill with Avalonia 12 migration guidance while keeping the rest of the repository pinned to Avalonia 11.3.12.
Current status for this guide:
12.0.0* tag on origin at that point: 12.0.0-rc1,12.0.0-rc1: March 19, 2026,12.0.0-rc1.Use this guide when you are porting an application, library, or samples from 11.3.12 toward Avalonia 12. The curated guidance below follows the current official Avalonia 12 docs page, while the generated API index and generated migration report in this repo remain source-backed against 12.0.0-rc1 until a newer Avalonia 12 tag exists upstream.
Use sources in this order for Avalonia 12 migration work:
Current generated evidence for this lane:
11.3.12 -> 12.0.0-rc1: 591 approved compatibility suppressions and 1175 added public signatures,12.0.0-preview2 -> 12.0.0-rc1: 168 added public signatures and 73 removed public signatures in the parser view.Coverage intent:
Handle these before you start fixing individual compile errors.
.NET Framework and .NET Standard..NET 8+,.NET 10,.NET 10.Practical rule:
The official docs page is written for the Avalonia 12 release line, not a mixed-package upgrade.
Practical rule:
Avalonia* package references together,12.0.0-rc1 as of March 20, 2026.The docs page now treats this as a first-class breaking change:
Avalonia.Diagnostics is removed,AvaloniaUI.DiagnosticsSupport,AttachDevTools() to AttachDeveloperTools().<AvaloniaUseCompiledBindingsByDefault> now defaults to true.
Practical rule:
x:DataType,{ReflectionBinding ...} only for real dynamic cases.UseSkia() directlyThe text shaper is now configured independently from the renderer.
Practical rule:
UsePlatformDetect() still gives you the standard text setup,.UseSkia(), add .UseHarfBuzz() and reference Avalonia.HarfBuzz.The official docs page calls out these removals:
Avalonia.Direct2D1,Avalonia.Browser.Blazor,Avalonia.Tizen,Avalonia.Diagnostics.These are the migration steps most likely to block the first successful build.
The docs page and generated diff agree on the core binding break:
IBinding is removed; use BindingBase,Binding remains only as the compatibility reflection-binding shape,InstancedBinding is removed; use BindingExpressionBase,ReflectionBinding and CompiledBinding directly,(path, mode) constructor overloads are gone; set Mode and other options explicitly.Migration rule:
using directives first,Avalonia 12 removes configurable binding plugins and disables the data-annotations plugin by default.
Migration rule:
System.ComponentModel.DataAnnotations, opt back in with AppBuilder.WithDataAnnotationsValidation(),UpdateDataValidation(...) overrides that only forwarded errors via DataValidationErrors.SetError(...).IDataObjectThe docs page is explicit here:
IDataObject is removed,DataObject no longer carries the old behavior,IClipboard now favors typed extension helpers,IDataTransfer / IAsyncDataTransfer / DataTransfer / DataTransferItem.Migration rule:
DataFormats.* with DataFormat.*,SetDataObjectAsync(...) with SetDataAsync(...),GetTextAsync() with TryGetTextAsync() and similar typed helpers,DragDrop.DoDragDropAsync(...) and DragEventArgs.DataTransfer.OpenFileDialog, OpenFolderDialog, SaveFileDialog, and related legacy dialog types stay removed on the Avalonia 12 line,TopLevel.StorageProvider and the FilePicker*Options types.TopLevel can no longer be treated as “the visual root plus every root service”Avalonia 12 changes the root-host model:
TopLevel is not guaranteed to be the root Visual,IInputRoot, ILayoutRoot, IRenderRoot, and related shapes,IPresentationSource is now part of the public host model,VisualExtensions.GetVisualRoot() is not the migration-safe path for this scenario anymore.Migration rule:
TopLevel.GetTopLevel(visual) to reach window/runtime services,GetPresentationSource(...) when you need the host/root bridge,This is one of the most visible app-facing breaks:
SystemDecorations became WindowDecorations,Window.ExtendClientAreaChromeHints was removed,TitleBar, CaptionButtons, and ChromeOverlayLayer were removed,WindowDrawnDecorations is the replacement managed-decoration surface.Migration rule:
SystemDecorations property usage to WindowDecorations,ExtendClientAreaToDecorationsHint,ExtendClientAreaChromeHints,WindowDecorationProperties.ElementRole and WindowDrawnDecorations-based patterns for custom chrome.Important official docs-page changes:
ShouldTriggerSelection(...) and UpdateSelectionFromEvent(...) for selection customization,Gestures class and are exposed directly on InputElement,AccessText.AccessKey changed from char to string?.Migration rule:
Gestures. prefix in XAML,AccessText.AccessKey.The official docs page also calls out these practical breaks:
FuncMultiValueConverter now takes IReadOnlyList<TIn>,Screen is abstract; do not construct it directly,ResourcesChangedEventArgs is now a struct; use ResourcesChangedEventArgs.Create() if you must create one,FontFeatureCollection to the trailing optional position.Treat these as first-pass fixes if your codebase touches them:
Avalonia.Direct2D1 is gone; use Skia,BinaryFormatter clipboard serialization on Windows is gone,Avalonia.Browser.Blazor is gone; use Avalonia.Browser and AvaloniaView,Avalonia.Tizen is gone from the main repository line.These are runtime checks, not just compile fixes.
Dispatcher.InvokeAsync(...) now captures execution context,AvaloniaObject.Dispatcher or Dispatcher.CurrentDispatcher for multi-dispatcher awareness,ExtendClientAreaToDecorationsHint behavior was fixed,.pfb / .pfm) are no longer supported,enableDataValidation: true should be re-tested because validation now flows automatically.Recommended verification passes:
Avalonia.Direct2D1 with Avalonia.Skia,BinaryFormatter,ExtendClientAreaToDecorationsHint workaround margins and title-bar hacks before re-adding anything.The docs page now expects this bootstrap shape:
MainActivity inherits plain AvaloniaMainActivity,[Application] type deriving from AvaloniaAndroidApplication<TApp>,IActivityApplicationLifetime.MainViewFactory,CreateAppBuilder() and CustomizeAppBuilder(...) on AvaloniaMainActivity.AvaloniaAppDelegate.Window stays null after initialization,UIWindow, detect it from AvaloniaView.MovedToWindow.Avalonia.Browser.Blazor,Avalonia 12 updates the supported unit-test baselines:
3,4.The official docs page is now the primary migration source, but the repository’s source-backed RC1 scan still exposes several app-facing deltas worth keeping in this guide because they affect real migrations.
The generated 11.3.12 -> 12.0.0-rc1 diff still surfaces important focus changes:
GotFocusEventArgs is replaced by FocusChangedEventArgs on GotFocus / LostFocus,FocusChangedEventArgs carries OldFocusedElement, NewFocusedElement, NavigationMethod, and KeyModifiers,IFocusManager.ClearFocus() assumptions no longer hold; move toward explicit focus transfer.Still relevant for touch-first shells and custom paging surfaces:
SwipeGestureRecognizer now uses CanHorizontallySwipe, CanVerticallySwipe, and IsMouseEnabled,CrossAxisCancelThreshold and EdgeSize are gone,SwipeGestureEventArgs now exposes incremental Delta plus Velocity,SwipeGestureEndedEventArgs was added.These are not from the official docs page, but they still matter if your code moved early:
DrawerBreakpointWidth became DrawerBreakpointLength,PipsPager landed after the preview2 baseline used by the earlier lane.Before:
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Avalonia.Diagnostics" Version="11.3.12" />
</ItemGroup>
public static AppBuilder BuildAvaloniaApp()
=> AppBuilder.Configure<App>()
.UseSkia();
After:
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AvaloniaUI.DiagnosticsSupport" Version="2.2.0" />
<PackageReference Include="Avalonia.HarfBuzz" Version="12.0.0-rc1" />
</ItemGroup>
public static AppBuilder BuildAvaloniaApp()
=> AppBuilder.Configure<App>()
.UseSkia()
.UseHarfBuzz();
Use AttachDeveloperTools() on the Avalonia 12 line.
Before:
using Avalonia.Data;
var nameBinding = new Binding("Customer.Name", BindingMode.TwoWay);
var titleBinding = new ReflectionBinding("WindowTitle", BindingMode.OneWay);
After:
using Avalonia.Data;
var nameBinding = new Binding("Customer.Name")
{
Mode = BindingMode.TwoWay
};
var titleBinding = new ReflectionBinding("WindowTitle")
{
Mode = BindingMode.OneWay
};
var dirtyBinding = CompiledBinding.Create<EditorViewModel, bool>(vm => vm.IsDirty);
Before:
var data = new DataObject();
data.Set(DataFormats.Text, "some text");
await clipboard.SetDataObjectAsync(data);
var text = await clipboard.GetTextAsync();
After:
var item = new DataTransferItem();
item.Set(DataFormat.Text, "some text");
var data = new DataTransfer();
data.Add(item);
await clipboard.SetDataAsync(data);
var text = await clipboard.TryGetTextAsync();
OpenFileDialog to StorageProviderBefore:
var dialog = new OpenFileDialog
{
AllowMultiple = false
};
var result = await dialog.ShowAsync(this);
After:
var topLevel = TopLevel.GetTopLevel(this)
?? throw new InvalidOperationException("No TopLevel available.");
var files = await topLevel.StorageProvider.OpenFilePickerAsync(
new FilePickerOpenOptions
{
AllowMultiple = false,
FileTypeFilter = new[]
{
new FilePickerFileType("Images")
{
Patterns = new[] { "*.png", "*.jpg" }
}
}
});
Before:
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
SystemDecorations="None"
ExtendClientAreaChromeHints="NoChrome"
ExtendClientAreaToDecorationsHint="True">
<Grid />
</Window>
After:
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:chrome="clr-namespace:Avalonia.Controls.Chrome;assembly=Avalonia.Controls"
WindowDecorations="None"
ExtendClientAreaToDecorationsHint="True">
<Grid>
<Button chrome:WindowDecorationProperties.ElementRole="CloseButton"
HorizontalAlignment="Right"
Content="Close" />
</Grid>
</Window>
Before:
<Button Gestures.Pinch="Button_Pinch" />
After:
<Button Pinch="Button_Pinch" />
Before (11.3.12):
[Activity(MainLauncher = true)]
public class MainActivity : AvaloniaMainActivity<App>
{
}
After (Avalonia 12 line):
[Application]
public class AndroidApp : AvaloniaAndroidApplication<App>
{
protected AndroidApp(nint javaReference, JniHandleOwnership transfer)
: base(javaReference, transfer)
{
}
}
[Activity(MainLauncher = true)]
public class MainActivity : AvaloniaMainActivity
{
}
If you need dynamic content creation on Android, prefer:
if (ApplicationLifetime is IActivityApplicationLifetime activityLifetime)
{
activityLifetime.MainViewFactory = () => new MainView();
}
ReflectionBinding explicit and local,AppBuilder.WithDataAnnotationsValidation() is still a reflection-heavy opt-in,CompiledBinding.Create(...) is the preferred code-only binding path for AOT-conscious code,Avalonia.Diagnostics.11.3.12.
x:DataType, switch to {CompiledBinding ...}, or explicitly opt a binding into {ReflectionBinding ...}.AttachDevTools() or Avalonia.Diagnostics no longer resolves.
AvaloniaUI.DiagnosticsSupport and AttachDeveloperTools().No text shaping system configured.
.UseSkia(), add .UseHarfBuzz() and reference Avalonia.HarfBuzz.IDataObject/DataObject usage with IDataTransfer / IAsyncDataTransfer / DataTransfer.Gestures. prefix in XAML.SystemDecorations to WindowDecorations, stop relying on ExtendClientAreaChromeHints, and use WindowDecorationProperties.ElementRole.[Application] type inheriting AvaloniaAndroidApplication<TApp> and that MainActivity inherits plain AvaloniaMainActivity.3 / NUnit 4 compatible versions.69-avalonia-12-breaking-changes-and-new-api-catalog.md,api-index-12.0.0-rc1-generated.md,