diff --git a/integrationtests/IntegrationTests.All.sln b/integrationtests/IntegrationTests.All.sln
index 89df742cb8..ddfbbae310 100644
--- a/integrationtests/IntegrationTests.All.sln
+++ b/integrationtests/IntegrationTests.All.sln
@@ -52,6 +52,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReactiveUI.Uwp", "..\src\Re
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReactiveUI.AndroidX", "..\src\ReactiveUI.AndroidX\ReactiveUI.AndroidX.csproj", "{824088E4-A1D2-4B71-843E-873D351073C8}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IntegrationTests.Avalonia", "IntegrationTests.Avalonia\IntegrationTests.Avalonia.csproj", "{556E134B-BA44-4885-A5F9-FB2D668F30A2}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ReactiveUI.Avalonia", "..\src\ReactiveUI.Avalonia\ReactiveUI.Avalonia.csproj", "{67F3CF51-1448-468E-BF86-4769F0EDF581}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Ad-Hoc|Any CPU = Ad-Hoc|Any CPU
@@ -1088,6 +1092,102 @@ Global
{824088E4-A1D2-4B71-843E-873D351073C8}.Release|x64.Build.0 = Release|Any CPU
{824088E4-A1D2-4B71-843E-873D351073C8}.Release|x86.ActiveCfg = Release|Any CPU
{824088E4-A1D2-4B71-843E-873D351073C8}.Release|x86.Build.0 = Release|Any CPU
+ {556E134B-BA44-4885-A5F9-FB2D668F30A2}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
+ {556E134B-BA44-4885-A5F9-FB2D668F30A2}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
+ {556E134B-BA44-4885-A5F9-FB2D668F30A2}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
+ {556E134B-BA44-4885-A5F9-FB2D668F30A2}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU
+ {556E134B-BA44-4885-A5F9-FB2D668F30A2}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
+ {556E134B-BA44-4885-A5F9-FB2D668F30A2}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
+ {556E134B-BA44-4885-A5F9-FB2D668F30A2}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {556E134B-BA44-4885-A5F9-FB2D668F30A2}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {556E134B-BA44-4885-A5F9-FB2D668F30A2}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU
+ {556E134B-BA44-4885-A5F9-FB2D668F30A2}.Ad-Hoc|x64.Build.0 = Debug|Any CPU
+ {556E134B-BA44-4885-A5F9-FB2D668F30A2}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
+ {556E134B-BA44-4885-A5F9-FB2D668F30A2}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
+ {556E134B-BA44-4885-A5F9-FB2D668F30A2}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
+ {556E134B-BA44-4885-A5F9-FB2D668F30A2}.AppStore|Any CPU.Build.0 = Debug|Any CPU
+ {556E134B-BA44-4885-A5F9-FB2D668F30A2}.AppStore|ARM.ActiveCfg = Debug|Any CPU
+ {556E134B-BA44-4885-A5F9-FB2D668F30A2}.AppStore|ARM.Build.0 = Debug|Any CPU
+ {556E134B-BA44-4885-A5F9-FB2D668F30A2}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
+ {556E134B-BA44-4885-A5F9-FB2D668F30A2}.AppStore|iPhone.Build.0 = Debug|Any CPU
+ {556E134B-BA44-4885-A5F9-FB2D668F30A2}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {556E134B-BA44-4885-A5F9-FB2D668F30A2}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {556E134B-BA44-4885-A5F9-FB2D668F30A2}.AppStore|x64.ActiveCfg = Debug|Any CPU
+ {556E134B-BA44-4885-A5F9-FB2D668F30A2}.AppStore|x64.Build.0 = Debug|Any CPU
+ {556E134B-BA44-4885-A5F9-FB2D668F30A2}.AppStore|x86.ActiveCfg = Debug|Any CPU
+ {556E134B-BA44-4885-A5F9-FB2D668F30A2}.AppStore|x86.Build.0 = Debug|Any CPU
+ {556E134B-BA44-4885-A5F9-FB2D668F30A2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {556E134B-BA44-4885-A5F9-FB2D668F30A2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {556E134B-BA44-4885-A5F9-FB2D668F30A2}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {556E134B-BA44-4885-A5F9-FB2D668F30A2}.Debug|ARM.Build.0 = Debug|Any CPU
+ {556E134B-BA44-4885-A5F9-FB2D668F30A2}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {556E134B-BA44-4885-A5F9-FB2D668F30A2}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {556E134B-BA44-4885-A5F9-FB2D668F30A2}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {556E134B-BA44-4885-A5F9-FB2D668F30A2}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {556E134B-BA44-4885-A5F9-FB2D668F30A2}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {556E134B-BA44-4885-A5F9-FB2D668F30A2}.Debug|x64.Build.0 = Debug|Any CPU
+ {556E134B-BA44-4885-A5F9-FB2D668F30A2}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {556E134B-BA44-4885-A5F9-FB2D668F30A2}.Debug|x86.Build.0 = Debug|Any CPU
+ {556E134B-BA44-4885-A5F9-FB2D668F30A2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {556E134B-BA44-4885-A5F9-FB2D668F30A2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {556E134B-BA44-4885-A5F9-FB2D668F30A2}.Release|ARM.ActiveCfg = Release|Any CPU
+ {556E134B-BA44-4885-A5F9-FB2D668F30A2}.Release|ARM.Build.0 = Release|Any CPU
+ {556E134B-BA44-4885-A5F9-FB2D668F30A2}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {556E134B-BA44-4885-A5F9-FB2D668F30A2}.Release|iPhone.Build.0 = Release|Any CPU
+ {556E134B-BA44-4885-A5F9-FB2D668F30A2}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {556E134B-BA44-4885-A5F9-FB2D668F30A2}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {556E134B-BA44-4885-A5F9-FB2D668F30A2}.Release|x64.ActiveCfg = Release|Any CPU
+ {556E134B-BA44-4885-A5F9-FB2D668F30A2}.Release|x64.Build.0 = Release|Any CPU
+ {556E134B-BA44-4885-A5F9-FB2D668F30A2}.Release|x86.ActiveCfg = Release|Any CPU
+ {556E134B-BA44-4885-A5F9-FB2D668F30A2}.Release|x86.Build.0 = Release|Any CPU
+ {67F3CF51-1448-468E-BF86-4769F0EDF581}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
+ {67F3CF51-1448-468E-BF86-4769F0EDF581}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
+ {67F3CF51-1448-468E-BF86-4769F0EDF581}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU
+ {67F3CF51-1448-468E-BF86-4769F0EDF581}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU
+ {67F3CF51-1448-468E-BF86-4769F0EDF581}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
+ {67F3CF51-1448-468E-BF86-4769F0EDF581}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
+ {67F3CF51-1448-468E-BF86-4769F0EDF581}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {67F3CF51-1448-468E-BF86-4769F0EDF581}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {67F3CF51-1448-468E-BF86-4769F0EDF581}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU
+ {67F3CF51-1448-468E-BF86-4769F0EDF581}.Ad-Hoc|x64.Build.0 = Debug|Any CPU
+ {67F3CF51-1448-468E-BF86-4769F0EDF581}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
+ {67F3CF51-1448-468E-BF86-4769F0EDF581}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
+ {67F3CF51-1448-468E-BF86-4769F0EDF581}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
+ {67F3CF51-1448-468E-BF86-4769F0EDF581}.AppStore|Any CPU.Build.0 = Debug|Any CPU
+ {67F3CF51-1448-468E-BF86-4769F0EDF581}.AppStore|ARM.ActiveCfg = Debug|Any CPU
+ {67F3CF51-1448-468E-BF86-4769F0EDF581}.AppStore|ARM.Build.0 = Debug|Any CPU
+ {67F3CF51-1448-468E-BF86-4769F0EDF581}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
+ {67F3CF51-1448-468E-BF86-4769F0EDF581}.AppStore|iPhone.Build.0 = Debug|Any CPU
+ {67F3CF51-1448-468E-BF86-4769F0EDF581}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {67F3CF51-1448-468E-BF86-4769F0EDF581}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {67F3CF51-1448-468E-BF86-4769F0EDF581}.AppStore|x64.ActiveCfg = Debug|Any CPU
+ {67F3CF51-1448-468E-BF86-4769F0EDF581}.AppStore|x64.Build.0 = Debug|Any CPU
+ {67F3CF51-1448-468E-BF86-4769F0EDF581}.AppStore|x86.ActiveCfg = Debug|Any CPU
+ {67F3CF51-1448-468E-BF86-4769F0EDF581}.AppStore|x86.Build.0 = Debug|Any CPU
+ {67F3CF51-1448-468E-BF86-4769F0EDF581}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {67F3CF51-1448-468E-BF86-4769F0EDF581}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {67F3CF51-1448-468E-BF86-4769F0EDF581}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {67F3CF51-1448-468E-BF86-4769F0EDF581}.Debug|ARM.Build.0 = Debug|Any CPU
+ {67F3CF51-1448-468E-BF86-4769F0EDF581}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {67F3CF51-1448-468E-BF86-4769F0EDF581}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {67F3CF51-1448-468E-BF86-4769F0EDF581}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {67F3CF51-1448-468E-BF86-4769F0EDF581}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {67F3CF51-1448-468E-BF86-4769F0EDF581}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {67F3CF51-1448-468E-BF86-4769F0EDF581}.Debug|x64.Build.0 = Debug|Any CPU
+ {67F3CF51-1448-468E-BF86-4769F0EDF581}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {67F3CF51-1448-468E-BF86-4769F0EDF581}.Debug|x86.Build.0 = Debug|Any CPU
+ {67F3CF51-1448-468E-BF86-4769F0EDF581}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {67F3CF51-1448-468E-BF86-4769F0EDF581}.Release|Any CPU.Build.0 = Release|Any CPU
+ {67F3CF51-1448-468E-BF86-4769F0EDF581}.Release|ARM.ActiveCfg = Release|Any CPU
+ {67F3CF51-1448-468E-BF86-4769F0EDF581}.Release|ARM.Build.0 = Release|Any CPU
+ {67F3CF51-1448-468E-BF86-4769F0EDF581}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {67F3CF51-1448-468E-BF86-4769F0EDF581}.Release|iPhone.Build.0 = Release|Any CPU
+ {67F3CF51-1448-468E-BF86-4769F0EDF581}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {67F3CF51-1448-468E-BF86-4769F0EDF581}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {67F3CF51-1448-468E-BF86-4769F0EDF581}.Release|x64.ActiveCfg = Release|Any CPU
+ {67F3CF51-1448-468E-BF86-4769F0EDF581}.Release|x64.Build.0 = Release|Any CPU
+ {67F3CF51-1448-468E-BF86-4769F0EDF581}.Release|x86.ActiveCfg = Release|Any CPU
+ {67F3CF51-1448-468E-BF86-4769F0EDF581}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -1101,6 +1201,7 @@ Global
{E6284535-0B6E-42AA-9113-5230AB09E8E6} = {34A7ABF0-30C6-48EA-94F0-8B116E995464}
{7B5A4E3B-8706-4D5B-B979-C5E39289CE17} = {34A7ABF0-30C6-48EA-94F0-8B116E995464}
{824088E4-A1D2-4B71-843E-873D351073C8} = {34A7ABF0-30C6-48EA-94F0-8B116E995464}
+ {67F3CF51-1448-468E-BF86-4769F0EDF581} = {34A7ABF0-30C6-48EA-94F0-8B116E995464}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {EDE6B0FD-3EF7-49C4-AF1D-E7485C1FEFAF}
diff --git a/integrationtests/IntegrationTests.Avalonia/App.axaml b/integrationtests/IntegrationTests.Avalonia/App.axaml
new file mode 100644
index 0000000000..a3760c31bb
--- /dev/null
+++ b/integrationtests/IntegrationTests.Avalonia/App.axaml
@@ -0,0 +1,8 @@
+
+
+
+
+
diff --git a/integrationtests/IntegrationTests.Avalonia/App.axaml.cs b/integrationtests/IntegrationTests.Avalonia/App.axaml.cs
new file mode 100644
index 0000000000..7abbc5bdcc
--- /dev/null
+++ b/integrationtests/IntegrationTests.Avalonia/App.axaml.cs
@@ -0,0 +1,28 @@
+// Copyright (c) 2024 .NET Foundation and Contributors. All rights reserved.
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for full license information.
+
+using Avalonia;
+using Avalonia.Controls.ApplicationLifetimes;
+using Avalonia.Markup.Xaml;
+
+namespace IntegrationTests.Avalonia;
+
+internal partial class App : Application
+{
+ public override void Initialize()
+ {
+ AvaloniaXamlLoader.Load(this);
+ }
+
+ public override void OnFrameworkInitializationCompleted()
+ {
+ if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
+ {
+ desktop.MainWindow = new MainWindow();
+ }
+
+ base.OnFrameworkInitializationCompleted();
+ }
+}
diff --git a/integrationtests/IntegrationTests.Avalonia/IntegrationTests.Avalonia.csproj b/integrationtests/IntegrationTests.Avalonia/IntegrationTests.Avalonia.csproj
new file mode 100644
index 0000000000..085a5f70c1
--- /dev/null
+++ b/integrationtests/IntegrationTests.Avalonia/IntegrationTests.Avalonia.csproj
@@ -0,0 +1,18 @@
+
+
+ WinExe
+ net8.0
+ Avalonia specific example of IntegrationTests
+ IntegrationTests.Avalonia
+ true
+
+
+
+
+
+
+
+
+
+
+
diff --git a/integrationtests/IntegrationTests.Avalonia/LoginControl.axaml b/integrationtests/IntegrationTests.Avalonia/LoginControl.axaml
new file mode 100644
index 0000000000..355e841647
--- /dev/null
+++ b/integrationtests/IntegrationTests.Avalonia/LoginControl.axaml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/integrationtests/IntegrationTests.Avalonia/LoginControl.axaml.cs b/integrationtests/IntegrationTests.Avalonia/LoginControl.axaml.cs
new file mode 100644
index 0000000000..003d005519
--- /dev/null
+++ b/integrationtests/IntegrationTests.Avalonia/LoginControl.axaml.cs
@@ -0,0 +1,63 @@
+// Copyright (c) 2024 .NET Foundation and Contributors. All rights reserved.
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for full license information.
+
+using System;
+using System.Reactive.Disposables;
+using System.Reactive.Linq;
+using IntegrationTests.Shared;
+using ReactiveUI;
+using ReactiveUI.Avalonia;
+
+namespace IntegrationTests.Avalonia;
+
+///
+/// Interaction logic for LoginControl.xaml.
+///
+[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
+public partial class LoginControl : ReactiveUserControl
+{
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public LoginControl()
+ {
+ InitializeComponent();
+
+ ViewModel = new LoginViewModel(RxApp.MainThreadScheduler);
+
+ this
+ .WhenActivated(
+ disposables =>
+ {
+ this
+ .Bind(ViewModel, vm => vm.UserName, v => v.Username.Text)
+ .DisposeWith(disposables);
+ this
+ .Bind(ViewModel, vm => vm.Password, v => v.Password.Text)
+ .DisposeWith(disposables);
+ this
+ .BindCommand(ViewModel, vm => vm.Login, v => v.Login)
+ .DisposeWith(disposables);
+ this
+ .BindCommand(ViewModel, vm => vm.Cancel, v => v.Cancel)
+ .DisposeWith(disposables);
+
+ ViewModel
+ .Login
+ .SelectMany(
+ result =>
+ {
+ if (result)
+ {
+ return this.ShowMessage("Login Successful", "Welcome!");
+ }
+
+ return this.ShowMessage("Login Failed", "Ah, ah, ah, you didn't say the magic word!");
+ })
+ .Subscribe()
+ .DisposeWith(disposables);
+ });
+ }
+}
diff --git a/integrationtests/IntegrationTests.Avalonia/MainWindow.axaml b/integrationtests/IntegrationTests.Avalonia/MainWindow.axaml
new file mode 100644
index 0000000000..7986a25b92
--- /dev/null
+++ b/integrationtests/IntegrationTests.Avalonia/MainWindow.axaml
@@ -0,0 +1,13 @@
+
+
+
+
+
diff --git a/integrationtests/IntegrationTests.Avalonia/MainWindow.axaml.cs b/integrationtests/IntegrationTests.Avalonia/MainWindow.axaml.cs
new file mode 100644
index 0000000000..412a4d5ac0
--- /dev/null
+++ b/integrationtests/IntegrationTests.Avalonia/MainWindow.axaml.cs
@@ -0,0 +1,17 @@
+// Copyright (c) 2024 .NET Foundation and Contributors. All rights reserved.
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for full license information.
+
+using Avalonia.Controls;
+
+namespace IntegrationTests.Avalonia;
+
+[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
+internal partial class MainWindow : Window
+{
+ public MainWindow()
+ {
+ InitializeComponent();
+ }
+}
diff --git a/integrationtests/IntegrationTests.Avalonia/Program.cs b/integrationtests/IntegrationTests.Avalonia/Program.cs
new file mode 100644
index 0000000000..451d9068d7
--- /dev/null
+++ b/integrationtests/IntegrationTests.Avalonia/Program.cs
@@ -0,0 +1,27 @@
+// Copyright (c) 2024 .NET Foundation and Contributors. All rights reserved.
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for full license information.
+
+using System;
+using Avalonia;
+using ReactiveUI.Avalonia;
+
+namespace IntegrationTests.Avalonia;
+
+internal static class Program
+{
+ // Initialization code. Don't use any Avalonia, third-party APIs or any
+ // SynchronizationContext-reliant code before AppMain is called: things aren't initialized
+ // yet and stuff might break.
+ [STAThread]
+ public static void Main(string[] args) => BuildAvaloniaApp()
+ .StartWithClassicDesktopLifetime(args);
+
+ // Avalonia configuration, don't remove; also used by visual designer.
+ public static AppBuilder BuildAvaloniaApp()
+ => AppBuilder.Configure()
+ .UsePlatformDetect()
+ .UseReactiveUI()
+ .LogToTrace();
+}
diff --git a/integrationtests/IntegrationTests.Avalonia/UserControlExtensions.cs b/integrationtests/IntegrationTests.Avalonia/UserControlExtensions.cs
new file mode 100644
index 0000000000..19a9a1d8f5
--- /dev/null
+++ b/integrationtests/IntegrationTests.Avalonia/UserControlExtensions.cs
@@ -0,0 +1,37 @@
+// Copyright (c) 2024 .NET Foundation and Contributors. All rights reserved.
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for full license information.
+
+using System;
+using System.Reactive.Threading.Tasks;
+using Avalonia.Controls;
+using MsBox.Avalonia;
+using MsBox.Avalonia.Enums;
+
+namespace IntegrationTests.Avalonia;
+
+///
+/// Extension methods associated with the UserControl class.
+///
+[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
+public static class UserControlExtensions
+{
+ ///
+ /// Shows a message to the user, and have the results wrapped in a observable.
+ ///
+ /// The user control that hosts the message box.
+ /// The title of the message box.
+ /// The message to show to the user.
+ /// An observable of the result from the message box.
+ public static IObservable ShowMessage(
+ this UserControl @this,
+ string title,
+ string message)
+ {
+ var window = (Window)TopLevel.GetTopLevel(@this)!;
+ var box = MessageBoxManager
+ .GetMessageBoxStandard(title, message);
+ return box.ShowWindowDialogAsync(window).ToObservable();
+ }
+}
diff --git a/src/Directory.Packages.props b/src/Directory.Packages.props
index f9a5c1b035..bd2e227166 100644
--- a/src/Directory.Packages.props
+++ b/src/Directory.Packages.props
@@ -43,6 +43,7 @@
+
diff --git a/src/ReactiveUI.Avalonia/AppBuilderExtensions.cs b/src/ReactiveUI.Avalonia/AppBuilderExtensions.cs
new file mode 100644
index 0000000000..47bc7da332
--- /dev/null
+++ b/src/ReactiveUI.Avalonia/AppBuilderExtensions.cs
@@ -0,0 +1,46 @@
+// Copyright (c) 2024 .NET Foundation and Contributors. All rights reserved.
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for full license information.
+
+using System;
+using Avalonia;
+using Splat;
+
+namespace ReactiveUI.Avalonia;
+
+///
+/// Avalonia AppBuilder setup extensions.
+///
+public static class AppBuilderExtensions
+{
+ ///
+ /// Initializes ReactiveUI framework to use with Avalonia. Registers Avalonia scheduler,
+ /// an activation for view fetcher, a template binding hook.
+ /// Remember to call this method if you are using ReactiveUI in your application.
+ ///
+ /// This builder.
+ /// The builder.
+ public static AppBuilder UseReactiveUI(this AppBuilder builder)
+ {
+ if (builder is null)
+ {
+ throw new ArgumentNullException(nameof(builder));
+ }
+
+ return builder.AfterPlatformServicesSetup(_ => Locator.RegisterResolverCallbackChanged(() =>
+ {
+ if (Locator.CurrentMutable is null)
+ {
+ return;
+ }
+
+ PlatformRegistrationManager.SetRegistrationNamespaces(RegistrationNamespace.Avalonia);
+ RxApp.MainThreadScheduler = AvaloniaScheduler.Instance;
+ Locator.CurrentMutable.RegisterConstant(new AvaloniaActivationForViewFetcher(), typeof(IActivationForViewFetcher));
+ Locator.CurrentMutable.RegisterConstant(new AutoDataTemplateBindingHook(), typeof(IPropertyBindingHook));
+ Locator.CurrentMutable.RegisterConstant(new AvaloniaCreatesCommandBinding(), typeof(ICreatesCommandBinding));
+ Locator.CurrentMutable.RegisterConstant(new AvaloniaObjectObservableForProperty(), typeof(ICreatesObservableForProperty));
+ }));
+ }
+}
diff --git a/src/ReactiveUI.Avalonia/Attributes.cs b/src/ReactiveUI.Avalonia/Attributes.cs
new file mode 100644
index 0000000000..16debf28bb
--- /dev/null
+++ b/src/ReactiveUI.Avalonia/Attributes.cs
@@ -0,0 +1,8 @@
+// Copyright (c) 2024 .NET Foundation and Contributors. All rights reserved.
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for full license information.
+
+using Avalonia.Metadata;
+
+[assembly: XmlnsDefinition("http://reactiveui.net", "ReactiveUI.Avalonia")]
diff --git a/src/ReactiveUI.Avalonia/AutoDataTemplateBindingHook.cs b/src/ReactiveUI.Avalonia/AutoDataTemplateBindingHook.cs
new file mode 100644
index 0000000000..5196439377
--- /dev/null
+++ b/src/ReactiveUI.Avalonia/AutoDataTemplateBindingHook.cs
@@ -0,0 +1,76 @@
+// Copyright (c) 2024 .NET Foundation and Contributors. All rights reserved.
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for full license information.
+
+using System;
+using System.Linq;
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Controls.Templates;
+using Avalonia.Layout;
+
+namespace ReactiveUI.Avalonia;
+
+///
+/// AutoDataTemplateBindingHook is a binding hook that checks ItemsControls
+/// that don't have DataTemplates, and assigns a default DataTemplate that
+/// loads the View associated with each ViewModel.
+///
+public class AutoDataTemplateBindingHook : IPropertyBindingHook
+{
+ private static readonly FuncDataTemplate DefaultItemTemplate = new FuncDataTemplate