11. Dez 2023
Lesedauer 12 Min.
Das bessere WPF
Cross-Platform User Interface Entwickeln mit Avalonia UI
Mit Version 11 stellt Avalonia UI ein XAML-basiertes UI-Framework für .NET zur Verfügung, das neben dem Desktop auch Mobile und Browser unterstützt.

Weshalb benötigt die .NET-Community ein weiteres User-Interface-Framework, wenn es doch schon so viele davon gibt? So mancher Entwickler hat sogar bereits den Überblick verloren.Die Antwort auf die Frage ist einfach: Genau deshalb. Zu welchem Zeitpunkt der Überblick abhandengekommen ist, ist weniger klar als die Ursache dafür.Es hat im Lauf der letzten gut 15 Jahre schlicht zu viele solcher Ansätze von Microsoft gegeben. Zahlreiche dieser Ansätze wurden entweder explizit eingestellt oder einfach nicht mehr weiterverfolgt.WinUI 3 und .NET MAUI sind die neuesten Lösungen aus Redmond, zu denen die Meinungen in der Community aber stark auseinandergehen [1].Eine Alternative zu diesen Frameworks ist das Open-Source-Projekt Avalonia UI (im Folgenden Avalonia), dessen Beliebtheit mit der Ankündigung von Version 11 vor über einem Jahr stark gestiegen ist (Bild 1). Das zeigt neben der NuGet-Download-Statistik [2] auch die wachsende Zahl großer Unternehmen wie Unity, JetBrains und GitHub, die auf Avalonia setzen [3]. Avalonia gehört zu den aktivsten Projekten der .NET Foundation [4]. Es lohnt sich also, dieses Framework genauer unter die Lupe zu nehmen.

Die Anwendung StuntSabers zur Konfiguration von Lichtschwertern à la Star Wars, entwickelt mit Avalonia [4] (Bild 1)
Autor
Was ist Avalonia?
Um Avalonia besser zu verstehen, ist es hilfreich, sich mit dem Namen des Frameworks auseinanderzusetzen. Avalon war der Codename von WPF zu Zeiten, als Microsoft das Framework entwickelt hat. Avalonia versteht sich selbst als geistiger Nachfolger von WPF. Der Gründer Steven Kirk wollte also die sehr guten Dinge von WPF beibehalten und die weniger guten Aspekte verbessern.Eine andere Annäherung an Avalonia findet man, wenn man die Lösungen betrachtet, mit denen Avalonia im Wettbewerb steht. Dies sind Qt/Qml [5] und Flutter [6]. Den meisten werden in dieser Auflistung UWP, WinUI 3, Xamarin, MAUI et cetera fehlen. Doch das hat seine guten Gründe.Avalonia wurde als Cross-Platform-Framework für die Desktop-User-Interface-Entwicklung konzipiert. Somit laufen Avalonia-Anwendungen also auf Windows, Linux und macOS.Neben klassischen Desktop-Anwendungen öffnet Avalonia durch die Kompatibilität zu Linux darüber hinaus die Tür zur Embedded-Entwicklung und greift damit dort an, wo Hersteller sowohl die spezialisierte Computer-Hardware als auch die Software mit dem User Interface liefern.Und das können oben genannte Lösungen von Microsoft eben nicht. Mit Version 11 sind Avalonia-Anwendungen jetzt auch kompatibel mit iOS und Android und können per WebAssembly (WASM) in der Browser-Umgebung starten. Dieser Artikel fokussiert aber auf die Desktop-Entwicklung.Ein weiterer Aspekt scheint auf den ersten Blick nur ein kleines Detail zu sein, ist aber von zentraler Bedeutung. Avalonia verfolgt den Ansatz, dass eine Anwendung auf jeder Plattform dieselben Pixel auf dem Bildschirm darstellt.Pixel-perfect Rendering ist überall da wichtig, wo Sie als Entwickler die Kontrolle über die Darstellung von Button, TextBox oder Scrollbar behalten wollen, und das unabhängig vom Betriebssystem.Das hindert Sie nicht daran, mit Avalonia eine Anwendung auf Windows mit einem Windows-11-Stil und auf macOS mit einem macOS-Stil darzustellen.MAUI beispielsweise verfolgt einen anderen Ansatz. Dort werden Native Controls zur Darstellung und Interaktion genutzt. Eine Mobile-App sieht also unter iOS wie andere iPhone-Apps aus und unter Android wie andere Android-Apps. Beide Ansätze haben ihre Berechtigung. Für Desktop-Entwicklung und insbesondere für Embedded-Entwicklung aber ist die Darstellung, die unabhängig vom darunterliegenden Betriebssystem ist, eine wichtige Anforderung.Im Wettbewerb der User-Interface-Frameworks, die genau diese Ziele verfolgen, hat Avalonia ein Alleinstellungmerkmal: Es ist das einzige Framework, das Ihnen die Entwicklung mit XAML und .NET ermöglicht.Hello Avalonia
Auch wenn sich dieser Artikel an Entwickler richtet, die WPF kennen und lieben, soll eine Hello-World-Anwendung zeigen, wie ähnlich sich Avalonia und WPF sind (Listing 1).Listing 1: Hello-World-Anwendung in Avalonia
MainWindow.axaml:<br/>&lt;Window xmlns=<span class="hljs-string">"https://github.com/avaloniaui"</span><br/> xmlns:x=<span class="hljs-string">"http://schemas.microsoft.com</span><br/><span class="hljs-string"> /winfx/2006/xaml"</span><br/> xmlns:d=<span class="hljs-string">"http://schemas.microsoft.com</span><br/><span class="hljs-string"> /expression/blend/2008"</span><br/> xmlns:mc=<span class="hljs-string">"http://schemas.openxmlformats.org</span><br/><span class="hljs-string"> /markup-compatibility/2006"</span><br/> mc:Ignorable=<span class="hljs-string">"d"</span> d:DesignWidth=<span class="hljs-string">"640"</span> <br/> d:DesignHeight=<span class="hljs-string">"480"</span><br/> x:Class=<span class="hljs-string">"HelloAvalonia.MainWindow"</span><br/> Title=<span class="hljs-string">"HelloAvalonia"</span> Width=<span class="hljs-string">"400"</span> <br/> Height=<span class="hljs-string">"300"</span>&gt;<br/> &lt;TextBlock Text=<span class="hljs-string">"Welcome to Avalonia!"</span><br/> HorizontalAlignment=<span class="hljs-string">"Center"</span><br/> VerticalAlignment=<span class="hljs-string">"Center"</span><br/> FontSize=<span class="hljs-string">"32"</span><br/> Foreground=<span class="hljs-string">"#8B44AC"</span>/&gt;<br/>&lt;/Window&gt;<br/>Program.cs<br/>internal <span class="hljs-keyword">class</span> <span class="hljs-title">Program</span><br/>{<br/> [STAThread]<br/> <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Main</span>(<span class="hljs-params"><span class="hljs-keyword">string</span>[] args</span>) </span>=&gt; <br/> BuildAvaloniaApp()<br/> .StartWithClassicDesktopLifetime(args);<br/> <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> AppBuilder <span class="hljs-title">BuildAvaloniaApp</span>(<span class="hljs-params"></span>)</span><br/><span class="hljs-function"> </span>=&gt; AppBuilder.Configure&lt;App&gt;()<br/> .UsePlatformDetect();<br/>}<br/>App.axaml<br/>&lt;Application xmlns=<span class="hljs-string">"https://github.com/avaloniaui"</span><br/> xmlns:x=<span class="hljs-string">"http://schemas.microsoft.com/</span><br/><span class="hljs-string"> winfx/2006/xaml"</span><br/> x:Class=<span class="hljs-string">"HelloAvalonia.App"</span><br/> RequestedThemeVariant=<span class="hljs-string">"Dark"</span>&gt;<br/> &lt;Application.Styles&gt;<br/> &lt;FluentTheme /&gt;<br/> &lt;/Application.Styles&gt;<br/>&lt;/Application&gt;<br/>App.axaml.cs (Auszug)<br/><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">override</span> <span class="hljs-keyword">void</span> </span><br/><span class="hljs-function"> <span class="hljs-title">OnFrameworkInitializationCompleted</span>(<span class="hljs-params"></span>)</span><br/>{<br/> <span class="hljs-keyword">if</span> (ApplicationLifetime <span class="hljs-keyword">is</span> <br/> IClassicDesktopStyleApplicationLifetime desktop)<br/> {<br/> desktop.MainWindow = <span class="hljs-keyword">new</span> MainWindow();<br/> }<br/> <span class="hljs-keyword">base</span>.OnFrameworkInitializationCompleted();<br/>}
Das MainWindow zeigt sich fast identisch mit der entsprechenden Variante für WPF. Ihnen ist vielleicht aufgefallen, dass die Dateien nicht .xaml, sondern .axaml als Dateinamenserweiterung verwenden. Das ist eine besondere Eigenschaft der Visual-Studio-Projektvorlagen, um Probleme bei der Interpretation der XAML-Dateien zu vermeiden.Ein Blick in den Program Startup Code (Program.cs) lässt schon erahnen, dass Avalonia mehr kann als Desktop-Anwendungen (StartWithClassicDesktopLifetime), denn das Builder-Entwurfsmuster in BuildAvaloniaApp erlaubt sowohl die automatische also auch die manuelle Steuerung des Startups. Es gibt zahlreiche Einstellungen, die es dem Entwickler erlauben, zum Beispiel unter Berücksichtigung des Betriebssystems bestimmte Einstellungen zu setzen.So wie das MainWindow liefert auch die Datei App.axaml wenig Unterschiede zu WPF. Dort wird die RequestedThemeVariant festgelegt, also ob die Anwendung im DarkMode oder im LightMode angezeigt wird, und welches generelle Theme für die Darstellung verwendet wird.In der dazugehörigen Codedatei (App.axaml.cs) erkennen Sie, welche Auswirkung die oben gewählte Startup-Variante StartWithClassicDesktopLifetime hat. Die ApplicationLifetime hat ein MainWindow, das Hauptfenster der Anwendung, das Sie für den Start zuweisen müssen.Das ist nicht beeindruckend genug? Auf den ersten Blick scheint unsere Beispielanwendung (Bild 2) noch recht wenig zu können. Sie stellt ein Fenster mit einem Text dar. Tatsächlich kann die Anwendung aber schon ziemlich viel: Ist das Projekt einmal in Visual Studio gebaut, können Sie den kompilierten Code im Ausgabeordner auf ein Linux- oder ein macOS-System kopieren, mit dotnet run starten und exakt denselben Fensterinhalt erkennen. Wenn man bedenkt, was dabei im Hintergrund alles funktionieren muss, ist die Lösung im Vergleich mit anderen Frameworks wie MAUI oder Platform UNO [7] schon sehr einfach. Diese Einfachheit wird durch die spezielle Architektur von Avalonia ermöglicht.

Hello Avalonia: Beispielanwendung (Bild 2)
Autor
Bevor wir zur Programmierung mit Avalonia kommen, soll ein Blick in diejenigen Architekturkomponenten erfolgen, die es erlauben, denselben Code und sogar dieselben Build-Artefakte auf Windows, Linux und macOS auszuführen und dabei das gleiche Anzeigeergebnis zu erhalten.
Die Avalonia-Architektur
Ein wichtiger Aspekt eines UI-Frameworks ist die Graphics Engine, also diejenige Komponente, die letztlich die Pixel erzeugt, die auf dem Bildschirm dargestellt werden. Avalonia verwendet dazu Skia [8] (siehe Bild 3), das unter anderem in Google Chrome, Mozilla Firefox, Android und Flutter verwendet wird. Skia ist plattformunabhängig und unterstützt mehrere Rendering-Technologien wie zum Beispiel OpenGL. OpenGL ist auch das Standard-Rendering-Backend in Avalonia, weil es auf allen Betriebssystemen gut unterstützt wird.
Avalonia-Architektur (Bild 3)
Autor
Neben OpenGL stellt Avalonia in Kürze auch ein Backend für Vulkan (Windows und Linux) zur Verfügung. Für Metal (macOS) gibt es bereits eine erste experimentelle Variante. Es ist denkbar, dass – wie bei Qt/Qml – künftig mehr und mehr Rendering-Backends zur Verfügung gestellt werden.Für Anwendungen, die einfache Steuerelemente verwenden, ist das nicht unbedingt notwendig. Bei der Integration von Video- oder 3D-Views ist es aber hinsichtlich der Performance sinnvoll, die für die Integration optimale Rendering-Technologie wählen zu können. Durch die Verwendung von Skia ist Avalonia hier flexibler als WPF, das nach wie vor auf dem veralteten DirectX 9 basiert.Zur Darstellung der durch Skia erzeugten Pixel auf den verschiedenen Betriebssystemen benötigt Avalonia vereinfacht gesagt nur ein natives Fenster, muss also das Windowing-System der Plattform ansteuern.In dieses Fenster wird ein Skia-Canvas eingebettet. Die Darstellung innerhalb dieses Canvas ist dann unabhängig vom Betriebssystem.Genau wie bei anderen Cross-Platform-UI-Frameworks sollte man die Anzahl und das Handling von Window minimieren. Der Window-Manager, also die Komponente, die für das Arrangieren der Fenster auf dem Desktop verantwortlich ist, agiert eben auf allen Betriebsystemen unterschiedlich. Innerhalb eines Fensters kann man sich dann sicher sein, dass die Darstellung auf jeder Plattform pixelgenau gleich ist.Aus WPF kennen Sie, dass es einen dedizierten UI-Thread gibt und dass Veränderungen an den Steuerelementen nur im UI-Thread erlaubt sind. Bei Avalonia ist das auch so. Ähnlich wie bei WPF gibt es die Möglichkeit, zu überprüfen, ob man sich im UI-Thread befindet, und falls nicht, die Programmausführung an den UI-Thread zu delegieren.
if (!Dispatcher.UIThread
.CheckAccess())
{
Dispatcher.UIThread.Post(action,
DispatcherPriority.Normal);
}
Moderne User-Interface-Frameworks verwenden einen vom UI-Thread getrennten Render-Thread, unter anderem, um den UI-Thread möglichst rasch wieder für Benutzereingaben bereitzustellen und auch die aktuellen Multi-Core-Prozessoren besser auszunutzen. Avalonia basiert ebenfalls auf diesem Konzept. Dieser Umstand ist wichtig, sobald man selbst in die Rendering-Pipeline eingreift, da dieses Threading-Konzept die Einhaltung bestimmter Regeln voraussetzt.
Avalonia-Elemente
Avalonia stellt den zu erwartenden Satz an Steuerelementen zur Verfügung, die Sie aus WPF kennen. Basiselemente wie TextBlock, TextBox oder Button haben dabei ganz bewusst dieselben Attribute wie bei WPF oder WinUI 3. Diese Namensgleichheit ist den Entwicklern von Avalonia wichtig, da sie den Einstieg erleichtert. Einige Steuerelemente sind dabei sogar einfach Portierungen aus WPF und funktionieren auch intern auf dieselbe Art und Weise.Ähnlich wie bei WPF sind Avalonia-Steuerelemente lookless. Sie implementieren also nur ein Verhalten und kein Aussehen. Das Aussehen – der Look – wird erst durch Styles definiert.Styles können zusammen ein Theme definieren. Für die Definition von Styles sind Selectors von zentraler Bedeutung.
<Window ... >
<Window.Styles>
<Style Selector="TextBlock.h1">
<Setter Property="FontSize" Value="24"/>
<Setter Property="FontWeight" Value="Bold"/>
<Style Selector="^:pointerover">
<Setter Property="Foreground" Value="Red"/>
</Style>
</Style>
</Window.Styles>
<StackPanel Margin="20">
<TextBlock Classes="h1">Heading 1</TextBlock>
</StackPanel>
</Window>
Das Styling-System besteht im Wesentlichen aus zwei Schritten: Auswählen und Ersetzen. In diesem Fall sucht der Selector alle Vorkommen von TextBlock aus, denen eine Klasse h1 zugewiesen ist. Für diesen TextBlock werden dann die entsprechenden Eigenschaften gesetzt. Das Zusammenspiel von Classes und Selector ist dabei ein entscheidender Faktor. Die Selector-Syntax ist der von CSS (Cascading Style Sheets) ähnlich. Styles können geschachtelt werden, wobei der innere Selector immer im Kontext des äußeren Selectors steht.Im obigen Beispiel wählt der innere Selector wieder den TextBlock aus, aber nur dann, wenn sich der Mauszeiger über dem entsprechenden Steuerelement befindet. Das syntaktische Element :pointerover ist in Avalonia eine PseudoClass, welche ähnlich wie die Classes zur Filterung dienen kann. PseudoClasses werden meist für den Verhaltenszustand von Steuerelementen verwendet (pressed, disabled, …).Sowohl Classes als auch PseudoClasses lassen sich im Code-behind setzen oder können in eigenen Steuerelementen erweitert werden.Zum Layouting stehen die aus WPF bekannten Panels zur Verfügung, unter anderem Canvas, DockPanel, Grid oder StackPanel. Auch hier gibt es kleinere Verbesserungen, wie man anhand des Beispiels von Grid sieht, das eine kompaktere Schreibweise für die Definition von Zeilen und Spalten erlaubt.
<Grid ColumnDefinitions="Auto,*,*,*,*"
RowDefinitions="Auto,Auto,*,Auto">
Teil des Layouting sind auch Animationen, von denen Avalonia derzeit zwei Arten unterstützt: Keyframe-Animationen und Transitions. Keyframe-Animationen sind die einfachste Art der Animation. Sie geben Marker (Cue) an, die den Ablauf der Animation steuern. Der Trigger einer Animation ist der zutreffende Selector. Keyframe-Animationen können auch kaskadiert werden, sodass eine Art Storyboard entsteht.
<Style Selector="TextBlock:pointerover">
<Style.Animations>
<Animation Duration="0:0:1.000">
<KeyFrame Cue="0%">
<Setter Property="Foreground" Value="Red"/>
</KeyFrame>
<KeyFrame Cue="100%">
<Setter Property="Foreground" Value="Yellow"/>
</KeyFrame>
</Animation>
</Style.Animations>
</Style>
Eine Alternative sind Transitions. Hier wird für eine Eigenschaft eines Steuerelements festgelegt, dass Änderungen dieser Eigenschaft durchgeführt werden, unabhängig davon, ob sie über einen Style oder im Code-behind gesetzt wird.
<TextBlock.Transitions>
<Transitions>
<BrushTransition Property="Foreground"
Duration="0:0:0.2"/>
</Transitions>
</TextBlock.Transitions>>
<TextBlock.Styles>
<Style Selector="TextBlock">
<Setter Property="Foreground" Value="Red"/>
</Style>
<Style Selector="TextBlock:pointerover">
<Setter Property="Foreground" Value="Yellow"/>
</Style>
</TextBlock.Styles>
MVVM
Komplexe XAML-basierte Anwendungen werden häufig nach dem Prinzip von Model-View-ViewModel (MVVM) erstellt. Das erfolgt in Avalonia-Anwendungen ähnlich wie in WPF. Wichtig für die Funktion von Bindings ist INotifyPropertyChanged. Eine ViewModelBase können Sie sich ohne Verwendung von weiteren Frameworks selbst erstellen.Avalonia unterstützt allerdings auch die Verwendung vonReactiveUI.
public class ViewModelBase :
INotifyPropertyChanged
{
public event
PropertyChangedEventHandler
PropertyChanged;
protected bool
RaiseAndSetIfChanged<T>(
ref T field, T value,
[CallerMemberName] string propertyName = null)
{
if (!EqualityComparer<T>.Default.Equals(
field, value))
{
field = value;
RaisePropertyChanged(propertyName);
return true;
}
return false;
}
protected void RaisePropertyChanged(
[CallerMemberName] string propertyName = null)
=> PropertyChanged?.Invoke(this,
new PropertyChangedEventArgs(propertyName));
}
Im ViewModel definieren Sie dann die Eigenschaften, die Sie in der View binden wollen.
ViewModel
private bool _isAllowed;
public bool IsAllowed
{
get => _ isAllowed;
set { RaiseAndSetIfChanged(ref _isAllowed, value); }
}
View
<TextBlock IsVisible="{Binding IsAllowed}"
Text="Mein Text"/>
Das Binding-Konzept von Avalonia ist etwas reichhaltiger als das von WPF. Sie können auf Properties von ViewModels binden, aber auch innerhalb der View auf andere Steuerelemente über deren Namen oder auch auf relative Vorgänger mit bestimmten Suchkriterien. Bei Avalonia basieren die relativen Bindings auf dem Logical Tree und nicht auf dem Visual Tree.Bindings für Listen, Commands und die Definition von Bindings aus dem Code werden ebenfalls unterstützt. Dabei haben Sie die Wahl zwischen CompiledBindings und ReflectionBindings. Avalonia empfiehlt aus Performancegründen, auf ReflectionBindings zu verzichten. Ein weiterer Vorteil von CompiledBindings ist, dass Sie mögliche Binding-Fehler bereits zum Übersetzungszeitpunkt erkennen.Welche der beiden Varianten Sie verwenden wollen, können Sie entweder für die gesamte Anwendung festlegen oder auch spezifisch pro Steuerelement.Für ein Steuerelement muss x:DataType festgelegt werden, damit das System weiß, auf welchen Datentyp gebunden wird.Die Festlegung von x:CompileBindings je Steuerelement ist nur notwendig, wenn sie nicht ohnehin auf Anwendungsebene definiert wurde. Sie können damit aber feingranular zwischen CompiledBindings und ReflectionBindings unterscheiden.
<UserControl ... x:DataType="vm:MyViewModel"
x:CompileBindings="True">
Die Binding-Syntax bleibt unabhängig vom gewählten Binding-Modus immer gleich. Gerade bei der Verwendung von Listen kann es sein, dass das System den Datentyp nicht automatisch ermitteln kann. In diesem Fall müssen Sie das System mit expliziten Cast-Anweisungen unterstützen.
<ItemsRepeater ItemsSource="{Binding MyItems}">
<ItemsRepeater.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding DisplayName}"/>
<Grid>
<Button Command="{Binding $parent[ItemsRepeater]
.((vm:MyUserControlViewModel)DataContext)
.DoItCommand}"
CommandParameter="{Binding ItemId}"/>
</Grid>
</StackPanel>
</DataTemplate>
</ItemsRepeater.ItemTemplate>
</ItemsRepeater>
Die Erstellung eigener Steuerelemente in Avalonia ist der in WPF sehr ähnlich, weshalb hier nicht im Detail darauf eingegangen wird. Die Benennung der Elemente hat Avalonia in diesem Fall gegenüber WPF geändert, um die Funktion der Elemente besser auszudrücken. UIElement und FrameworkElement aus WPF entsprechen Control in Avalonia, während Control aus WPF TemplatedControl in Avalonia entspricht.Ein Control in Avalonia hat einen Look, ein TemplatedControl ist lookless. DependencyProperty aus WPF entspricht StyledProperty und DirectProperty in Avalonia. AttachedProperties, RoutedEvents et cetera stehen ebenfalls zur Verfügung. Im Kasten Weiterführende Informationen zu Avalonia finden Sie eine Zusammenstellung von Links, die Ihnen den Einstieg in Avalonia erleichtern und auch die hier vorgestellten Elemente im Detail erläutern.
Listing 1: Hello-World-Anwendung in Avalonia
MainWindow.axaml:<br/>&lt;Window xmlns="https://github.com/avaloniaui"<br/> xmlns:x="http://schemas.microsoft.com<br/> /winfx/2006/xaml"<br/> xmlns:d="http://schemas.microsoft.com<br/> /expression/blend/2008"<br/> xmlns:mc="http://schemas.openxmlformats.org<br/> /markup-compatibility/2006"<br/> mc:Ignorable="d" d:DesignWidth="640" <br/> d:DesignHeight="480"<br/> x:Class="HelloAvalonia.MainWindow"<br/> Title="HelloAvalonia" Width="400" <br/> Height="300"&gt;<br/> &lt;TextBlock Text="Welcome to Avalonia!"<br/> HorizontalAlignment="Center"<br/> VerticalAlignment="Center"<br/> FontSize="32"<br/> Foreground="#8B44AC"/&gt;<br/>&lt;/Window&gt;<br/>Program.cs<br/>internal class Program<br/>{<br/> [STAThread]<br/> public static void Main(string[] args) =&gt; <br/> BuildAvaloniaApp()<br/> .StartWithClassicDesktopLifetime(args);<br/> public static AppBuilder BuildAvaloniaApp()<br/> =&gt; AppBuilder.Configure&lt;App&gt;()<br/> .UsePlatformDetect();<br/>}<br/>App.axaml<br/>&lt;Application xmlns="https://github.com/avaloniaui"<br/> xmlns:x="http://schemas.microsoft.com/<br/> winfx/2006/xaml"<br/> x:Class="HelloAvalonia.App"<br/> RequestedThemeVariant="Dark"&gt;<br/> &lt;Application.Styles&gt;<br/> &lt;FluentTheme /&gt;<br/> &lt;/Application.Styles&gt;<br/>&lt;/Application&gt;<br/>App.axaml.cs (Auszug)<br/>public override void <br/> OnFrameworkInitializationCompleted()<br/>{<br/> if (ApplicationLifetime is <br/> IClassicDesktopStyleApplicationLifetime desktop)<br/> {<br/> desktop.MainWindow = new MainWindow();<br/> }<br/> base.OnFrameworkInitializationCompleted();<br/>}
IDE-Integration
Sie sehen also, dass Sie sich als WPF-Entwickler in Avalonia sehr schnell zurechtfinden. Für die Akzeptanz ist aber nicht nur die Funktion des Frameworks, sondern auch die Entwicklungsumgebung entscheidend. Avalonia ermöglicht die Entwicklung mit Visual Studio [9] und Visual Studio for Mac, Visual Studio Code [10] und JetBrains Rider [11]. Die reichhaltigste Integration bietet dabei JetBrains Rider, deren IDE-Erweiterung aus dem eigenen Hause stammt. Außerdem ermöglicht Rider die Entwicklung unter Windows, Linux und macOS. Aber auch die IDE-Erweiterungen der Visual-Studio-Varianten bieten alle notwendigen Funktionen. Diese enthalten Projektvorlagen, XAML Code Completion und einen integrierten Previewer (Bild 4).
Avalonia Previewer in Visual Studio Code [10] (Bild 4)
Autor
Sie vermissen einen Designer? In der Tat gibt es in den Avalonia-IDE-Erweiterungen keinen Drag-and-drop-Designer. Darauf wurde bewusst verzichtet, da die View-Entwickler bei nicht trivialen Ansichten ohnehin den WPF-Designer nicht verwenden, sondern selbst die Kontrolle über den XAML-Code behalten. Dafür bietet der Avalonia Previewer einen erweiterten Funktionsumfang gegenüber dem WPF-Designer. Er zeigt in einer Split-View live die Vorschau dessen an, was Sie im XAML-Code ändern, und erlaubt eine explizite Steuerung der Designansicht. Entwickeln Sie beispielsweise ein Steuerelement, das in verschiedenen Zuständen unterschiedlich angezeigt wird (zum Beispiel Button pressed, disabled, …), kann der Previewer alle diese Zustände gleichzeitig anzeigen. Er ist also in der Lage, beliebig viele Instanzen desselben Steuerelements als Vorschau anzuzeigen. Das erleichtert insbesondere die Entwicklung von eigenen Basis-Steuerelementen oder Styles für bestehende Steuerelemente.Der Previewer ermöglicht darüber hinaus echte Laufzeitinteraktion, sodass Sie Animationen oder Mausinteraktionen direkt im Vorschaufenster ausprobieren können. Für viele Änderungen können Sie also Ihre Implementierung testen, ohne überhaupt die Anwendung ausführen zu müssen. Gerade bei komplexen Anwendungen, bei denen Sie erst nach einigen manuellen Schritten zu derjenigen Ansicht gelangen, an der Sie gerade Änderungen vornehmen, ermöglicht diese Funktion kurze Turnarounds.Zur Inspektion der laufenden Anwendung gibt es die Avalonia DevTools (Bild 5). Während der Ausführung der Anwendung in der Debug-Konfiguration können Sie die DevTools mit [F12] starten und darin durch den Logical Tree und den Visual Tree navigieren. Sie können Eigenschaften von Steuerelementen einsehen und auch live ändern, sodass sie in der Anwendung appliziert werden.

Avalonia DevTools (Bild 5)
Autor
Fazit
Mit Avalonia UI v11 steht ein modernes User-Interface-Framework zur Verfügung, das sich einerseits an Entwickler wendet, die bislang mit XAML-basierten Lösungen von Microsoft gearbeitet haben, sich aber auch als Alternative zu Qt/Qml und Flutter sieht. Als geistiger Nachfolger von WPF macht Avalonia den Umstieg leicht und bietet darüber hinaus viele Verbesserungen.User-Interface-Entwickler können damit Desktop-Anwendungen entwickeln, die auf Windows, Linux und macOS identisch aussehen, ohne dabei betriebssystemspezifischen Code schreiben zu müssen. Das ermöglicht kein anderes .NET-basiertes UI-Framework. Avalonia ist für die Desktop-Entwicklung production-ready und bietet IDE-Integration für die wichtigen .NET-Entwicklungsumgebungen.Die Möglichkeit, dieselbe Technologie auch für die Entwicklung von Mobile-Apps und Browser-Anwendungen nutzen zu können, wird die Zahl der Nutzer von Avalonia weiter steigern. Immer mehr große Unternehmen nutzen bereits Avalonia. Die Entwickler stellen dafür bezahlten Support und kundenspezifische Entwicklung zur Verfügung. Die Dokumentation [12] ist mit v11 vollständig überarbeitet und die Firmenstruktur den neuen Bedürfnissen angepasst.Avalonia hat das Potenzial, das meistgenutzte User-Interface-Framework für .NET zu werden. Es wird spannend, wie Avalonia den Spagat zwischen Desktop- und Mobile-Entwicklung besteht und wie gut die Anpassung an die steigende Anzahl der Nutzer gelingt.Fussnoten
- [1] Fabian Deitelhoff, Was lange währt, dotnetpro 2/2023, Seite 8 ff., http://www.dotnetpro.de/A2302MAUI
- [2] Avalonia NuGet, http://www.dotnetpro.de/SL2401Avalonia1
- [3] Programme mit Avalonia, https://avaloniaui.net/Showcase
- [4] Stuntsabers, https://stuntsabers.eu
- [5] Qt, http://www.qt.io
- [6] Flutter, https://flutter.dev
- [7] UNO Platform, https://platform.uno
- [8] Skia, https://skia.org
- [9] Avalonia for Visual Studio 2022, http://www.dotnetpro.de/SL2401Avalonia2
- Preview von Avalonia for Visual Studio Code, http://www.dotnetpro.de/SL2401Avalonia3
- Plug-in für Jetbrains Rider, http://www.dotnetpro.de/SL2401Avalonia4
- Offizielle Dokumentation, http://www.dotnetpro.de/SL2401Avalonia5
- Forum, http://www.dotnetpro.de/SL2401Avalonia6
- Community-Support für Telegram und Gitter, http://www.dotnetpro.de/SL2401Avalonia7
- Tutorial auf YouTube, http://www.dotnetpro.de/SL2401Avalonia8
- Control-Katalog, http://www.dotnetpro.de/SL2401Avalonia9
- Bezahlter Support, http://www.dotnetpro.de/SL2401Avalonia10