A Cross-Platform GUI Theme for Desktop .NET Core Applications
Avalonia is a novel XAML UI framework, allowing .NET developers to deliver cross-platform .NET Core desktop applications for end-users. Inspired by Microsoft stack technologies, such as Xamarin Forms, Windows Presentation Framework, and Universal Windows Platform, Avalonia provides fully-featured means of building high-performant user interfaces of any complexity and any scale. Compared to Windows Presentation Framework, Universal Windows Platform, or Xamarin Forms, Avalonia provides a faster type-safe XAML compiler known as XamlIl, which makes the process of developing and debugging complex XAML interfaces far less painful. Moreover, XamlIl allows debugging XAML — watch this video on YouTube if you are still in doubt about giving Avalonia a try. Avalonia comes with ReactiveUI support out of the box, and this makes it possible to use the full power of reactive programming in an Avalonia .NET Core app.
Known Avalonia applications include its use in a cross-platform IDE and shell, in code editors, and in privacy-focused Bitcoin wallets. Avalonia is shipped as .NET Standard MIT-licensed NuGet packages and is available for free for anyone willing to build cross-platform desktop experiences in C# or F#, even for commercial use.
However, the ecosystem around the framework is still developing — there aren’t many GUI themes developed for the framework yet. Hence, designing a brand new modern style set seemed reasonable to me. User interface themes in Avalonia were designed as standalone components that can be easily replaced with any other sets of styles, and this made the development process of different color schemes even more simple and convenient.
The styling system in Avalonia can be thought of as a mix of CSS styling and WPF styling, a style consists of a selector and a collection of setters. Styles can be defined on any control, importing styles from files or packages is supported as well.
Avalonia styling system also supports pseudo-classes, which allows us to control the look of controls in different visual states. With the help of this feature, we can easily change the background of a button when a user presses it, or when a user moves the mouse over the control. Using the
/template/ syntax, we can style the primitives based on which a more complex control is built. Dynamic and static resources are also supported, which may seem familiar for those coming from WPF, UWP, or Xamarin Forms.
Based on the mentioned implementation details, a novel graphical user interface theme was introduced and packed as a NuGet package. The theme received the name Citrus because of the orange accent color used in most of the color schemes available in the
Citrus.Avalonia NuGet package. Following the licensing policy of the Avalonia framework, the Citrus theme is MIT-licensed and free for everyone, even for commercial use. The source code of the project is available on GitHub.
If you are completely new to Avalonia, see Avalonia Getting Started tutorial on their documentation website. After you have created the Avalonia .NET Core project, the
Citrus.Avalonia package can be installed by either using the NuGet package manager GUI of any IDE, including JetBrains Rider and Microsoft Visual Studio. Another way is to execute the following .NET Core SDK command from your project root:
dotnet add package Citrus.Avalonia
Then, place the following XAML code into the
StyleInclude line is responsible for importing a set of styles into the application. The imported styles will be applied to all default XAML controls, descendant to the element which contains the
StyleInclude line. As a result of the code snippet above, all default controls in your application will start using Citrus styles. If you are willing to apply the styles to a small part of your application, move the
StyleInclude line to the
Styles section of control other than
Application . Notably, the Citrus NuGet package includes a dark color scheme as well.
To browse the control gallery, clone the
Citrus.Avalonia.Sandbox sample project. There are five color schemes total available inside the
Citrus.Avalonia NuGet package, named Citrus, Sea, Rust, Candy, and Magma. In order to use color schemes other than the default one, you need to adjust the
StyleInclude XAML tag by changing the
Source attribute to point to another color scheme. To avoid collisions, remember to remove other
StyleInclude lines present in the
App.xaml file before.
Changing Color Schemes Dynamically
In order to provide end-users the ability to change graphical user interface themes dynamically, move the
StyleInclude line to a control other than
Application . The
StyleManager class shown below takes in a
Window via the constructor, and provides the ability to change UI themes at runtime via the
UseTheme method invocation.
See Avalonia Documentation for further details about building custom themes and adjusting styles. The source code of the Citrus theme described in this post may help as well, in case if you are going to build your own GUI theme. The sandbox project contains the control gallery shown in the pictures contained in this post. If you encounter any issues regarding the Avalonia GUI framework or the Citrus theme, head over to Avalonia Gitter. See the article Building Cross-Platform Reactive .NET Apps for more insight into the architecture used in XAML-based cross-platform C# applications.
Further work could cover more UI design guidelines. Folks from the Avalonia community have started working on the Material Design theme. Additionally, worth implementing the new Microsoft Fluent Design System and Apple Human Interface Guidelines.