WinUI 3 Preview 3

Alexandre

WinUI 3

At Ignite 2019 Microsoft released the first bits of Windows UI Library (WinUI) version 3 (a.k.a. WinUI 3), an evolution of the UWP/XAML platform, that decouples the XAML UI framework from the Windows OS. It is shipped in its whole as a NuGet package, effectively allowing developers to support new features of XAML on older versions of Windows 10 without the need of end-users to upgrade their OS. Instead of relying on the XAML bits being shipped on the OS, the WinUI team literally refactored the whole XAML source code to ship it as a simple NuGet package. You can see the latest road map here. This work has been happening for a while now, with new bits being released every few months.

Since the Windows 8.x era, Microsoft has been evolving the UWP XAML framework to support new form factors and different hardware, like touch screen devices and pen enabled screens. It also provides the best-in-class native support allowing developers to leverage it through both .NET and C++ applications. However, since the UWP APIs and the XAML UI framework have been extremely tied together there has been no way to leverage the new UI improvements from a Win32 application. At least until XAML Islands was released, back in 2018, where Microsoft enabled Win32 developers to also leverage the UWP XAML technology. WinUI 3 can also be leveraged in a similar way, through a technology we’ll talk about in this article called WinUI Desktop.

 

Native Windows Apps

The first thing to note is that UWP applications and Win32 applications (either .NET or C++) are both native Windows applications, and they are both supported by Microsoft. They fill different needs for different applications and end users. You can’t build an Xbox app with Win32, as UWPs fill that role, and you can’t build a Windows driver with UWP. Each process execution model has its own role and place in the Windows ecosystem, and they complement each other.

UWP apps run inside a sandbox that keeps you from having access to the whole operating system as you mostly can through Win32 APIs, and these Win32 APIs exist since 1985 (Windows 1.0). Yes, Microsoft still support those same APIs. And it’s not because it’s an old ~~tech~~ process execution model that it needs to use an old UI framework. That is the beauty of WinUI Desktop. You can leverage the latest and greatest native UI stack on our oldest process execution model, which gives you more flexibility for creating your applications. Within this blog post, we’ll build a WinUI Desktop app using C#, .NET5 and WinUI3 Preview 3.

Important! This WinUI 3 preview release is intended for early evaluation and to gather feedback from the developer community. It should NOT be used for production apps.

Microsoft will continue shipping preview releases of WinUI 3 throughout 2020 and into 2021, after which the first official release will be made available.

Please use the WinUI GitHub repo to provide feedback and log suggestions and issues.

C#/WinRT

Another interesting step towards decoupling the XAML UI framework from the Windows OS is how you access those APIs, specially through managed languages, like C#. The Windows SDK is mostly written in C++ and, as I’ve mentioned before, you can use the Windows SDK from mostly any language. This interop works through an abstraction layer called Windows Runtime (WinRT), which is basically the evolution of COM, and a matching projection for each specific language. C++ developers already have a projection to access those APIs through a thing called C++/WinRT. C# developers had that as well, but it was embedded inside the UWP C# compiler and runtime (and was removed in .NET 5). This is where the C#/WinRT project comes. It provides the WinRT projections for C#, hiding the details of the interop between C# and WinRT, and is shipped as a simple NuGet package, completely decoupled from the Windows SDK.

By lifting this projection out of the compiler and the runtime Microsoft is enabling the use of .NET5 with XAML applications. For most developers, C#/WinRT is an implementation detail and won’t affect you much, but if you are authoring a library, it is important to understand how to provide these projections alongside your existing DLLs/WinMDs. This is a breaking change from an authoring perspective of .NET Core 3.1, so if that affects you, take a moment to read through the docs to provide these projections for your library. There is also a very good blog post about C#/WinRT.

 

WinUI Desktop basics

Now that you know the theory, let’s actually use WinUI 3.0.0-preview3 in a simple Win32/Desktop application. You need VS 2019 16.9 Preview1+, and the Visual Studio templates for WinUI 3.0.0-preview3. You can see all requirements here.

Once in VS Preview with the templates installed, simply create a new WinUI Desktop project:

New WinUI Desktop App

Give the project a name, a location, and select the min version of Windows where you want your application to be supported. That is actually one of WinUI3’s benefits. Since anything from the MUX (Microsoft.UI.Xaml.*) namespace is lifted from the OS, you know that it will be available wherever your app is running. There is no need to specify a newer minimum OS version to use a newer XAML API, which simplifies your development, without the need to check for XAML APIs availability. Conditional XAML, for purely accessing newer XAML APIs that were not available on older OS versions, is pretty much obsolete with WinUI3. You might still want to use it for showing different UIs for, let’s say, only show a “Connect Bluetooth LE 5 device” button on an newer OS version that has Bluetooth LE 5 support, since only XAML related APIs are lifted on WinUI3, but for anything from XAML itself, you can freely call any API and it should be available at all OS versions where WinUI3 is supported.

New WinUI Desktop App SDK Selection

Since I’m not using any API that is particularly new, I’ve selected the oldest version where WinUI3 runs on as the minimum version, which is 1803.

Now that the solution and its projects are created, let’s take a quick look at how this template initiates our project.

Visual Studio Solution Explorer.

We don’t see a single project, but two projects. That is due to the fact that WinUI3, as of preview3, requires an App ID to run, and since WinUI Desktop is a Win32 application (which doesn’t have an App Id by default), we need to provide this somehow. The correct solution to this problem is packaging the Win32 project through a Packaging project (MSIX), which is what the “WinUI3Preview3Sample (Package)” project is. It simply references the main Win32 project and adds an AppXManifest file.

The structure of our main WinUI Desktop project is very familiar to any UWP developer. You have an App.xaml/App.xaml.cs file, and a Main*Something*.xaml/Main*Something*.xaml.cs file. In UWP, this *Something* was a Page. In WinUI Desktop, this *Something* is a new concept called Window, similar to WPF’s Window. Inside App.xaml, we have a simple initialization of WinUI’s Resource Dictionary, as any UWP with WinUI2 app needs to do today. WinUI's App.xaml file.

Our App.xaml.cs, on the other hand, is slightly different and simpler from our UWP counterpart: WinUI's App.xaml.cs file. We only need to instantiate our MainWindow class and call it’s Activate method. This loads the main window and shows it to the user.

This is our simple Window’s Xaml implementation: WinUI's MainWindow.xaml file.

We have a simple StackPanel and a button inside it. Clicking on the button triggers the myButton_Click event, that exists in our MainWindow.xaml.cs file: WinUI's MainWindow.xaml.cs file.

And the only thing that this simple code does is change the button’s Content (e.g. its text) to “Clicked”.

Now that we know how our project is structured, let’s run it! This should be as simple as selecting the right platform and pressing F5 to build, run, and see the magic happen:

Visual Studio Solution Explorer.

It will build and pack your Win32 app inside the packaging project, and automatically install it in your system.

WinUI Desktop App - First run.

And when you click on the button: WinUI Desktop App - Clicked on button.

Very simple app, but we can evolve from here. Instead of changing the button’s text to “Clicked”, let’s prove that this is a Win32 app. Let’s call a user32.dll method directly into this window’s HWND. Fun!

I’ve chosen a very simple Win32 API called SetWindowPos which enables me to, for example, move the window around. But before we can call this API, we need to take a hold of this window’s HWND, which is not that simple. The window from a WinUI Desktop app implements an interface that contains a reference to this HWND, but its not exposed publicly by WinUI’s API layer for us to use. Luckily, C#/WinRT can help! We just need to know which interface that class is implementing internally, and ask C#/WinRT to give us a representation of this object as an object that implements this interface. The hard part is to know/provide the right interface. Once we have that, we call the .As<T>() method from C#/WinRT and get the property that contains that HWND, with which we can do pretty much anything with.

WinUI's new MainWindow.xaml.cs file.

And just like that, if you run your app again, when you click on the button, it will move the window around! Isn’t that amazing? I just love when we mix the old and the new in a seamless way. The possibilities are endless! You can even use the Windows Community Toolkit, which has a preview version that supports WinU3!

Wrapping up

That was our first WinUI Desktop app. Its a simple one, but you can see how we can easily leverage the amazing Windows UI stack from a Win32 application with a straight-forward Visual Studio template. Now its your time to create beautiful, complex, fully-featured applications with WinUI Desktop.

Checkout the source of the code of the sample shared here.

We welcome your feedback in the WinUI GitHub repo.

25 comments

Comments are closed. Login to edit/delete your existing comments

  • Chris Baker

    Hi, I may be missing something in my understanding, but why is this so different from what I can do already using WPF? Surely WinUI is just UWP with another name and UWP was, well, basically, rubbish. So I can’t see any benefit to WinUI, why can’t Microsoft just spend some effort in improving WPF?

    • Alexandre Zollinger ChohfiMicrosoft employee

      Hello Chris.
      If WPF fits your needs, you can still use it. WinUI is just another option that allows not only C# developers, but also C++ developers to build native applications. WinUI is much more touch friendly than WPF, and leveraging some new windows APIs, like the Camera API is much easier from WinUI. You also have much more control of the Xaml rendering with the Visual Layer in WinUI, or even in in UWP, compared to what you have in WPF.
      But, again, if WPF fits your needs, you should use it. I would not migrate just because.

  • Nigel Pearce

    Within this new project configuration am I right in thinking that it isn’t possible to make use of existing third party software libraries that target .Net 4.x ?

    • Alexandre Zollinger ChohfiMicrosoft employee

      Yes, that is correct. WinUI3 uses .NET 5, which is not compatible with .Net 4.x. Also, if you need to use any specific library that is not netstandard only, lets say a UWP library, they would also need to move to WinUI3, since its a different UI stack.

  • Peter N. Moore

    Please man, the word is THROUGH not THRU. It hurts my eyes to read this post.

  • MgSam

    It’s surprising to me MS hasn’t pulled the plug on UWP yet. Usage of it is tiny- even Microsoft itself barely uses it for its apps. It’s been nearly 10 years since the Windows 8 disaster- I think it’s time to let Metro apps die already in favor of something cross platform.

  • Mircea Zahan

    Oh my, this is soooo good news, I’m so very glad they’ve decoupled it from the OS. Now I can finally drop it! I hope ….

  • Elliot Richards

    Thank you for this write-up, Alexandre.

    We still use MFC for some of our software products, simply because there really hasn’t been a viable alternative UI layer for that “native” C++ code. These are “system” applications that need full access to the underlying OS facilities in order to do their jobs, so they often can’t be achieved at all in sandboxed environments.

    Am I correct in understanding that WinUI 3 will allow us to continue using native C++ code while gradually replacing/updating the UI? That would be ideal, as our apps benefit greatly from the low-level memory control afforded by C++.

    • Me Gusta

      My understanding of this is that on release, it will require packaged applications but support for non packaged applications will come in a future update.

      Packaged applications themselves can access the underling OS facilities, but they have to be installed in the same way as Windows Store apps (think of things like the Windows Terminal). But non packaged applications are what you would think of the regular Windows API applications.

      • Alexandre Zollinger ChohfiMicrosoft employee

        Correct. WinUI3.0 requires an App Id, so the project templates already create a packaging project. It is on the roadmap for a future version, post-3.0, to support non-MSIX deployment.

  • Rafael Vasco

    This was a great article Alexandre ! High 5 from a fellow C# developer from Brazil! Looking up to use this in my projects.

  • Rand Random

    Can you clarify this remark for me?


    Important! This WinUI 3 preview release is intended for early evaluation and to gather feedback from the developer community. It should NOT be used for production apps.

    Microsoft will continue shipping preview releases of WinUI 3 throughout 2020 and into 2021, after which the first official release will be made available.

    Please use the WinUI GitHub repo to provide feedback and log suggestions and issues.

    Since we are already in 2021, this statement seems off?
    Did you meant to say there will be preview releases throughout 2021 and 2022 will have the first official release, or is the first official release around the corner?

  • LiFei

    I think. Net should be solved first 5.0 deployment problem, it has to be said that the powerful Microsoft does not even have a decent packaging tool. In addition to independent compilation and MSI packaging, the developers are too complicated to deploy. I think most developers do not want to distribute a program with a volume of one or two hundred MB. Why not start a program without running time and give the user a confirm button to download and install it immediately instead of sending it to the user It’s a puzzling webpage that pops up. Most customers don’t know which webpage you should download or what you should do. I have to say it’s too hasty. Winui3, an empty application, generates a directory of 300 + MB and a package of 100MB. It’s really unpleasant to distribute in this way. So there are too few developers who like uwp and winui. Even the running environment is subject to various restrictions. Who will give winui too much affection