RoyalApps.Community.Avalonia.Windows
1.2.0
Prefix Reserved
dotnet add package RoyalApps.Community.Avalonia.Windows --version 1.2.0
NuGet\Install-Package RoyalApps.Community.Avalonia.Windows -Version 1.2.0
<PackageReference Include="RoyalApps.Community.Avalonia.Windows" Version="1.2.0" />
paket add RoyalApps.Community.Avalonia.Windows --version 1.2.0
#r "nuget: RoyalApps.Community.Avalonia.Windows, 1.2.0"
// Install RoyalApps.Community.Avalonia.Windows as a Cake Addin #addin nuget:?package=RoyalApps.Community.Avalonia.Windows&version=1.2.0 // Install RoyalApps.Community.Avalonia.Windows as a Cake Tool #tool nuget:?package=RoyalApps.Community.Avalonia.Windows&version=1.2.0
Utilities and Helpers for AvaloniaUI
RoyalApps.Community.Avalonia
RoyalApps.Community.Avalonia contains projects/packages for AvaloniaUI.
RoyalApps.Community.Avalonia.Windows
This package contains a WinFormsControlHost with a custom lifecycle management. XAML based controls like the TabControl in Avalonia, detach and attach views dynamically when switching between tabs. In general, this is a good approach to make rendering and resource utilization efficient.
Putting a NativeControlHost in such a view can cause issues because every time the view gets detached and another one attached, the native control is destroyed and recreated. If you want to host legacy WinForms controls, for example, you might want to have more control over the lifetime of your user control.
The demo application as shown above, creates a view with a WinFormsControlHost for each tab. The WinForms control (also part of the demo app), simply contains a text box, prints an "instance id" and has a random background color to demonstrate that the instances "survive" and keep the state until manually disposed.
Installation
Install the RoyalApps.Community.Avalonia.Windows with NuGet:
Install-Package RoyalApps.Community.Avalonia.Windows
or via the command line interface:
dotnet add package RoyalApps.Community.Avalonia.Windows
Using the WinFormsNativeHost Control
Add the Control
You can find the WinFormsControlHost
in the namespace RoyalApps.Community.Avalonia.Windows.NativeControls
:
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:winForms="clr-namespace:InteropDemo.WinForms;assembly=InteropDemo.WinForms"
xmlns:nativeControls="clr-namespace:RoyalApps.Community.Avalonia.Windows.NativeControls;assembly=RoyalApps.Community.Avalonia.Windows"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="InteropDemo.Views.TestView"
Padding="10">
<nativeControls:WinFormsControlHost x:Name="WinFormsControlHost" x:TypeArguments="winForms:TestControl" />
</UserControl>
Note
Since the control is a generic typeWinFormsControlHost<T> where T : System.Windows.Forms.Control
, you need to specify the type of your WinForms control you want to host in thex:TypeArguments
attribute.
By default, the WinFormsControlHost<T>
creates a new instance of your type automatically and keeps track of the instance. You can subclass the control and override the OnCreateWinFormsControl()
method to create and return the instance of the WinForms control yourself.
To configure your control (e.g. set properties), use the OnLoaded()
override:
protected override void OnLoaded()
{
base.OnLoaded();
if (WinFormsControlHost.Control is not { } testControl)
return;
testControl.BackColor = Color.White;
}
Manage the Lifetime of the Control
In the view model you use as data context where you placed the WinFormsControlHost
, simply implement the IDisposeWinFormsControl
interface:
public partial class TabViewModel : ViewModelBase, IDisposeWinFormsControl
{
[ObservableProperty] private string _caption = "n/a";
public event EventHandler<WinFormsDisposeEventArgs>? DisposeWinFormsControl;
[RelayCommand] public void Close() => App.MainViewModel.RemoveTab(this);
public void RaiseTabClosing()
{
DisposeWinFormsControl?.Invoke(this, new WinFormsDisposeEventArgs(this));
}
}
Simply invoke the DisposeWinFormsControl
event and pass the instance of the view model to the WinFormsDisposeEventArgs
constructor.
How does it work?
The singleton class WinFormsLifetimeManager
keeps the instances of all WinForms controls in a dictionary as long as they are required (not manually disposed).
Note
The view model instance (which implementsIDisposeWinFormsControl
) will be used askey
for the dictionary. Depending on your view model implementation, you might see issues with this approach whenGetHashcode
orEquals
is overridden.
The WinFormsControlHost
inherits from NativeControlHost
and prevents the control from being destroyed. When an instance of the WinForms control is requested for a specific view model, you either get an existing instance if available, or an instance is created for you.
When you are done (e.g. the view model is getting removed for good), you invoke the DisposeWinFormsControl
event on your view model to signal the WinFormsLifetimeManager
the WinForms control can be destroyed/disposed.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net8.0-windows7.0 is compatible. net9.0-windows was computed. net9.0-windows7.0 is compatible. |
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.