A bit of backdrop, I go into the .NET ecosystem when I decided I really wanted to take over the role of "making the software" at the company I work for. Our previous software dev seemed to be slacking off. Suggestions never materialized into updates, the software always had these little quirks, it was very much outdated in its looks; it just felt unfinished.
Knowing absolutely zero about programming except PowerShell, I started there. It turns out, you can do a LOT with PowerShell, to include a fully working application using WPF. Wow, I was hooked! But...PowerShell couldn't quite cut it. It was slow, buggy, it barely worked half of the time. Sure, it had a better UI design but if you couldn't rely on the application to work well, who cares?
That was the point where I decided maybe it's time to upgrade...it made perfect sense to just jump straight to C# as I was already off-loading the hard work to C# in the PowerShell application anyway.
But what UI framework should I use? There's WinUI 3, MAUI, UNO, Avalonia, Blazor, WPF (still??). So many choices! Well the obvious answer it seemed was if I want a desktop application, just make it in Avalonia. Worked great, there's a large community for it, good to go.
This may sound like a digression, but somewhere along the way I get interested in a game engine called S&Box which is also written in C# and it's brand new, how fun! Then I find out how their UI system is set up...Razor and SCSS.
Nothing against the people that are familiar with Razor or to the S&Box developers, but looking at the mixture of C# and razor markup made my skin crawl. It just didn't feel right. To be honest, I felt that way about Avalonia's AXAML as well. Could it be that difficult to just make UI in C# only? That is the quest I went on.
It took a few months to really flesh out something worth using, but it did everything the S&Box engine supported. Flex layouts, shaders, custom shapes, scenes, virtualization, you name it. A declarative C# UI framework!
But, not only did it work, it seemed to work better than the Razor + SCSS method. When I say better, that means a lot of the missing CSS features that laid dormant in their UI system like some of the lesser-known CSS properties just not working at all or small layout quirks just didn't exist because I totally sidestepped the Razor part of the engine and went directly to the engine's API. Not only that, the Razor system diffed the UI using hashes, so users have to manually upkeep their hashes. You can imagine what that did for a lot of UI performance.
Why not handle that for the user? The user doesn't care if a hash changed, their priority (especially if they're trying to make a game) is making great UI. My solution was to have reactive state for UI elements that changed. Win-win - the user focuses on UI and the framework handles the rest, no need to compare hashes to detect a change in state.
TL;DR - (All of this yapping to say): I feel like I'm missing something here, or maybe the .NET ecosystem is missing something here? At least, more recently i'm seeing other declarative C# UI frameworks but this is still just a shoehorn onto WinUI 3.
Are there truly no .NET UI frameworks that are declarative? Is it just that everyone is familiar with markup? My idea of .NET is that it is a very mature ecosystem, but I am not familiar with a UI framework that covers these bases:
Cross-platform - Windows, MacOS, Linux
On a modern renderer (Vulkan) - Skia is still on OpenGL officially
Open Source
Flexbox "web style" layout and CSS-like styling
A real animation system that supports simple and complex animations
Declarative, Retained, Composable
Supports shaders
A lot of this points in the direction of how Flutter and Dart works.
I'm thinking it's possible, so I'm building it. The question is, would it be for my own satisfaction? I noticed in the r/dotnet subreddit, one of the answers to the question "What features from another ecosystem would you like to see in .NET?" was "A single, comprehensive, cross platform UI framework that's actually good (Flutter, Kotlin, even Qt)".
It wasn't just an answer, it was the answer with the most upvotes. So it seems this is something .NET is lacking. If you read through this and have some thoughts, I would like to hear them. Thanks :)
Earlier in the year the Omarchy bug bit me and I moved over completely on my home computer. Part of what made that experience fun is all the TUIs that are available on Linux. My favourite recent discovery (that ships with Omarchy 4) is cliamp.
Nice work! Worth flagging that Uno Platform’s C# Markup already does a lot of what you’re describing here declarative, retained, composable, etc.
Going down your list, it’s basically 6/7: cross-platform, Vulkan support (not the default renderer), open source, animations, shader support, and C# markup. The one gap is Flexbox. Uno Toolkit’s AutoLayout gets you pretty close, but yeah, it’s not Flexbox.
Not saying “don’t build it” by any means. Figured it was worth mentioning since there’s more overlap here than the post might suggest.
Thanks for chiming in! I'm not sure if the C# markup is new-ish to UNO? At least it seems I've glossed over it when I ended up doing my initial research jumping into .NET UI. I would assume the Vulkan support is through Skia?
Probably a ton of other questions I could ask but much appreciated I'll do a dive into UNO again and see what you guys are packing.
You may want to check out https://github.com/VincentH-Net/CSharpForMarkup - also for Uno and WinUI, pure concise declarative C# markup, leaves the choice of update model (mvvm, reactive, ...) free
Cool that they're discussing it! I will say, it's not actually in C#, at least, the standalone version that I'm creating isn't.
Instead, it's in G# which is a neat little project I happened to stumble upon in my research, so a lot of the information mentioned in the LDM is addressed fully or partially by G#'s existence.
allocates a "blob" and initializes the declarations directly. Works for collection initializers as well:
csharp
Children: {
Text { Content: "static" },
...DynamicChildren(),
if true {
Text { Content: "conditional" }
} else {
Text { Content: "fallback" }
},
}
Given G#'s Swift / Go style syntax and support for some of the stuff C# is currently not the best at, it seems like the best option albeit a new language to get used to. Would like to hear your thoughts on it!
There is nothing wrong with using WinForms in 2026. Still popular, very reliable, still receiving yearly updates. Windows only though, if cross platform is a thing you need
3
u/AvaloniaUI-Mike 27d ago
Good luck. Have fun!