After K2, the Kladde runs in the browser. This course gives it a Windows program: a desktop application with a window of its own, navigation, keyboard operation and the features that users expect from a Windows program. The tool for that is called WinUI 3, and it belongs to the Windows App SDK. This lesson clarifies what both are and what they are not, sets up your machine, creates src/Kladde.Desktop from a template, and shows how a WinUI project is built and how quickly you can change a user interface in it.

The course assumes K2: C# and async, the Kladde's web API with its sign-in through Entra ID, and xUnit. This course does not repeat that; where it builds on it, there is a reference. You may know XAML and MVVM from the course W2 .NET MAUI: this course says what is the same and what WinUI 3 does differently, but it does not assume W2.

Module Lesson What you build
W5.1 W5.1.1 WinUI 3 and the Windows App SDK at a glance the project Kladde.Desktop, startable as a window
W5.1 W5.1.2 XAML, layouts and navigation pages for appointments and contacts with NavigationView, a dialog for deleting
W5.2 W5.2.1 MVVM, dependency injection and tests the pages as view models in a library of their own, tested without a window
W5.2 W5.2.2 Data: API, sign-in and cache appointments from the web API, with sign-in, cached locally
W5.3 W5.3.1 The app window, lifecycle and notifications window state, a single instance, a reminder as a notification
W5.3 W5.3.2 Testing, packaging, distributing an MSIX package, signed and installed on a second machine

State of the checks. This course was written on a machine on which the Windows App SDK, the WinUI templates and the winapp CLI are not set up. Every command line and every line of XAML and C# in this lesson comes from the reference and examples on Microsoft Learn or was read against them. It was not run against a real WinUI project. Where the lesson describes what appears on the screen, it describes it according to Learn; it does not reproduce any output that was measured. Where Learn does not say something, the text says so ("Learn says nothing about this, check ..."). If your observation differs from the lesson, your observation counts, and you write it down.

What the Windows App SDK is

According to Learn, the Windows App SDK is the recommended development platform for new Windows desktop applications. It is a set of programming interfaces that comes through NuGet and is shipped independently of the operating system. As a result, new features reach your application without Windows itself having to be updated. It runs on Windows 11 and on Windows 10 from version 1809.

Learn names these components:

Component What it is for
WinUI the native framework for the user interface, with C# or C++ and XAML, in the style of Fluent Design
Windowing create, position and customize windows
App lifecycle instance management, rich activation (file, protocol, restart), power management
Resource management strings and images per language, scaling and contrast variant, separate from the program logic
Notifications local app notifications and push notifications from the cloud
Widgets information in the Widgets area of Windows
XAML Islands WinUI controls in existing desktop applications
Deployment ship the Windows App SDK runtime with the application, packaged or unpackaged
Windows AI APIs, Windows ML AI features and local ONNX models; this course does not teach them
modern text rendering device-independent text layout with ClearType

You determine the version on the download page of the Windows App SDK; it changes every month. For that reason, this course names no version numbers apart from "Windows App SDK 2". There are three channels: Stable for production (the default in the documentation), Preview and Experimental. The course stays with Stable.

What WinUI 3 is

According to Learn, WinUI 3 is the recommended native user interface framework for new Windows desktop applications. It works with XAML, it exists for C# and C++, and it runs on x86, x64 and ARM. Parts of the Windows user interface and PowerToys are built with it. WinUI 3 is the part of the Windows App SDK that fills windows; everything else in the table above (lifecycle, notifications, resources) can be used independently of it.

This sentence is the most important one in the lesson: The Windows App SDK is the platform, WinUI 3 is its user interface. Whoever says "WinUI" usually means both in everyday talk. In this course, "Windows App SDK" is used when windows, lifecycle or notifications are meant, and "WinUI" or "XAML" when it is about controls and pages.

Where WinUI 3 stands: WPF, Windows Forms, UWP, .NET MAUI

Four neighbors come up in every discussion. Here is one paragraph on each, without any judgment on what you already have in production.

WPF and Windows Forms. Both remain valid for existing applications; whoever maintains such an application, moves it to .NET 10 or brings it to the web and to Azure will find that in the course "Modernization: WinForms/WPF to .NET 10, the web and Azure", not here. Learn names two bridges: first, the Windows App SDK can be built into existing WPF, Windows Forms and Win32 projects; the parts that have nothing to do with WinUI (application lifecycle, windowing, app notifications) can be used there. Second, WinUI XAML Islands bring WinUI controls into part of an existing application, for example as a new screen in a WPF program. Learn distinguishes them from the older "system XAML Islands", which host UWP controls and use other interfaces; the two must not be mixed. More on both is in the Modernization course and in the pages under "Further reading"; this course teaches neither WPF nor Windows Forms nor a migration.

UWP. The Windows App SDK does not support UWP applications. For programs that are UWP today, Learn names the path "Migrate from UWP to the Windows App SDK"; namespaces, project model and individual interfaces differ, many concepts remain. The course does not cover UWP any further.

.NET MAUI. MAUI is a cross-platform framework for mobile devices and desktop; on Windows it builds on WinUI 3. It pays off when the same user interface is supposed to run on Android, iOS, macOS and Windows (course W2 .NET MAUI). WinUI 3 runs only on Windows and talks to the Windows interfaces directly: whoever builds a program for Windows that feels like a Windows program is in the right place with WinUI 3. Both use XAML; what looks the same is not named the same (for example, pages, navigation and controls have different names), and lesson W5.1.2 goes into that.

WinUI 3 itself. For new Windows programs, it is the path that Learn recommends. What follows from that for your decision depends on whether the application is new, on which Windows versions it has to run, and on who maintains it later; the course gives no judgment.

What this course is not

  • Not an introduction to C# or Entra ID. You bring both from K0 to K2.
  • Not cross-platform. For that there is W2 .NET MAUI.
  • No WPF, no Windows Forms, no migration (course Modernization).
  • No game development and no C++/WinRT. C++ exists for WinUI 3 as well; the course stays with C#.
  • No depth on the Windows AI interfaces. They are in the table; the course does not teach them.

Tools

For the first steps, Learn names two paths. Both are fine, and both lead to the same result, a project that you keep working on in your tool:

Visual Studio winapp CLI
Prerequisite Visual Studio in the current release (Learn names it on the quickstart page) with the workload "WinUI application development", plus Developer Mode the .NET 10 SDK, the Windows App Development CLI, Developer Mode
Editor Visual Studio any editor and a terminal
Run F5 winapp run
Special XAML Hot Reload, Live Visual Tree, debugger with breakpoints, also in XAML Learn calls the winapp CLI public preview; for this path, from version 0.6

The winapp CLI does not install the .NET SDK; according to Learn, winapp new and winapp run stop with a message if it is missing. With WinGet:

PowerShell
winget install --id Microsoft.DotNet.SDK.10 --exact --source winget
winget install --id Microsoft.WinAppCli --exact --source winget

Then open a new terminal so that it finds the commands, and check the versions:

PowerShell
dotnet --version
winapp --version

Learn requires .NET SDK 10 or newer and winapp CLI 0.6 or newer. For Visual Studio, Learn shows a way to set up the required workloads and Developer Mode with a WinGet configuration file:

PowerShell
winget configure -f https://aka.ms/winui-config

Read the configuration before you run it: it changes your machine (Visual Studio workloads, Developer Mode). Learn links a description of the configuration for this. If you prefer to work by hand, install Visual Studio and choose the workload WinUI application development in the Visual Studio Installer.

In addition, independent of the path: the WinUI 3 Gallery. It shows every control with examples; you get it from the Microsoft Store or build it from the source on GitHub (repository microsoft/WinUI-Gallery). The example there is often the shortest way to find the XAML lines of a control.

Developer Mode

For both paths, Learn requires Windows Developer Mode: Windows needs it to register the app from your output. You turn it on in Settings (for the Windows 11 window, Learn names: System, For developers; the labels change between Windows versions). Turning it on requires administrator rights and can be blocked on company devices. If the deployment later reports that Developer Mode is off, this is the cause. What the mode changes on your machine is described by Learn on a page of its own about the security of the winapp CLI; read it if the machine does not belong to you alone.

Templates

For Visual Studio and for dotnet new, Learn names these C# project templates:

Template Short name What it creates
WinUI Blank App (Packaged) winui an empty, packaged project with one window
WinUI Navigation App winui-navview a project with a navigation bar
WinUI TabView App winui-tabview a project with tabs
WinUI MVVM App winui-mvvm a project with an MVVM skeleton
WinUI Class Library winui-lib a library that uses WinUI types
WinUI Unit Test App winui-unittest a test project that runs inside a WinUI application

There are also item templates for an existing project: Blank Page, Blank Window, Content Dialog, Resource Dictionary, Resources File (.resw), Templated Control and User Control. On the command line, for example, dotnet new winui-page -n SettingsPage adds a page; dotnet new list winui lists all templates. The short names of the project templates in the table are the ones Learn names; if dotnet new list winui shows something different on your machine, the list on your machine counts.

The course starts with the empty template because you can name every file in it. The lessons W5.1.2 and W5.2.1 build the navigation skeleton and MVVM themselves, so that you know what is in the template if you do take it later after all.

Creating the project

With Visual Studio: Create a new project, search for WinUI, choose the C# template WinUI Blank App (Packaged), enter a name and location, press F5. The first time, a window about Developer Mode may appear; Learn mentions it as a note in the flow, and also that Visual Studio installs another package for it.

With the winapp CLI, from a folder where you keep your projects:

PowerShell
winapp new --name MyWinUIApp --template winui --use-defaults
cd MyWinUIApp
winapp run

According to Learn, winapp new creates the empty WinUI application and winapp run builds the project and starts it; no build and registration instruction of your own is needed. Learn shows the command for a folder named after the project (cd MyWinUIApp). Whether winapp new has an option for a target folder is not stated on the pages that were read: change into the folder where the project is supposed to be created first, and look after the command to see where it ended up.

Learn points out that the templates differ: in the current template of the CLI, MainPage.xaml contains an empty <Grid />; if this file is missing in your template, the content is in MainWindow.xaml. That is no small matter when you read examples: which of the two files your template has determines where the first content goes.

For the first change, Learn shows this content in the page (or in the window):

xaml
<Grid>
    <TextBlock
        Text="Hello, WinUI!"
        HorizontalAlignment="Center"
        VerticalAlignment="Center" />
</Grid>

If the page already has controls, add only the TextBlock into the existing area and leave names and event handlers in place. Do not replace the surrounding Page, the Window, or the frame and title bar in MainWindow.xaml. Save, restart (winapp run or F5). According to Learn, the window shows the text.

If nothing appears, Learn names these checks:

Observation What you check
winapp or dotnet is not recognized reopen the terminal after the installation, run the version commands from above
winapp new is not recognized this path requires winapp CLI 0.6 or newer: update
the WinUI templates are missing in Visual Studio choose Modify in the Visual Studio Installer, check the workload, restart Visual Studio
the build reports an SDK or restore error read the first error of the output, check the prerequisites of the path, read the page "Windows App SDK support" for version requirements before you change project properties
the deployment reports that Developer Mode is off turn Developer Mode on and restart
the new message does not appear save the XAML file and restart the app; in templates with MainPage.xaml, add the message in the page, not in the window

Kladde.Desktop

For the Kladde, you create the project later in the same place as the projects from K2. The division applies to the whole course:

Project Content When
src/Kladde.Desktop the WinUI application, packaged: window, pages, App.xaml from this lesson
src/Kladde.Desktop.Logic a plain net10.0 library: view models, services, interfaces, no XAML types W5.2.1
tests/Kladde.Desktop.Logic.Tests xUnit tests for this library W5.2.1

The reason for the separation is in the testing section of Learn: code that needs Microsoft.UI.Xaml types runs only on the UI thread of a XAML application. Learn recommends moving code into a library that application and test both reference. W5.2.1 puts that into practice; until then there is only the application project.

How a WinUI project is built

Learn describes the files you deal with most (tutorial "Project setup" of the WinUI Notes walkthrough):

File or folder Purpose
Assets logo, images and other media; at the start, placeholders for the logo that represents the application in the Start menu, in the taskbar and in the Store
App.xaml and App.xaml.cs in XAML, the resources for the whole application (colors, styles, templates); in code, usually creating and activating the window
MainWindow.xaml and MainWindow.xaml.cs the application's window
Package.appxmanifest the package manifest: publisher, logos, processor architectures and further details that determine how the application appears
the project file (.csproj) target framework, references, package settings

Every XAML file has a code-behind file. In it, the XAML file declares the class with the attribute x:Class, and both are parts of the same partial class. The XAML file describes the user interface, the code-behind file reacts to events and changes the objects that were created in XAML. Learn names these characteristics that prove a project is WinUI 3 and not a UWP, WPF or MAUI project:

  1. The project file contains <UseWinUI>true</UseWinUI>.
  2. It references the package Microsoft.WindowsAppSDK.
  3. The XAML code and the C# code use types from Microsoft.UI.Xaml.
  4. Package.appxmanifest provides the package identity.
  5. The target framework contains Windows; Learn names net10.0-windows10.0.26100.0 as an example.

Check this in your project. Your target framework may differ from the example, depending on what your template sets.

The namespaces are the most common stumbling block for people with WPF or UWP experience: WinUI 3 uses Microsoft.UI.Xaml and Microsoft.UI.Xaml.Controls, not Windows.UI.Xaml. Learn shows it in a tutorial on working with an AI assistant: there is an example with using Windows.UI.Xaml.Controls; and the note that this is the UWP namespace and wrong for WinUI 3; the right one is Microsoft.UI.Xaml.Controls (and the dialog there additionally lacks the XamlRoot, more on that in W5.1.2). A glance at the using lines is the fastest check of someone else's code example, whether from an assistant, from a forum or from an old article.

How the application starts

App.xaml.cs is the entry point. The class App derives from Application, and its method OnLaunched runs when the application is started. The window is created there. In the reference for the class Page, Learn shows an example of how the pieces work together when an application puts a Frame into the window and navigates to a page:

C#
protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
{
    m_window = new MainWindow();

    // Create a Frame to act as the navigation context.
    Frame rootFrame = new Frame();

    rootFrame.NavigationFailed += OnNavigationFailed;

    // Place the frame in the current Window
    m_window.Content = rootFrame;

    rootFrame.Navigate(typeof(MainPage), args.Arguments);

    m_window.Activate();
}

This is an example of a pattern, not the content of your template: on the pages that were read, Learn does not say what exactly OnLaunched contains in the winui template. Open App.xaml.cs in your project and read it. The patterns from the example are the building blocks you will find again in the templates: a window is a Microsoft.UI.Xaml.Window, it is created and made visible with Activate(), a Frame is a container for pages (Frame.Navigate(typeof(...))), a page is a Page. In W5.1.2 you use a Frame with page navigation.

A note on the term window: according to Learn, Window from WinUI is an abstraction over the lower-level kinds of windows (CoreWindow in UWP, the window handle in Win32). The fact that Window has no XamlRoot property, while the element inside it does, is the cause of the dialog error in W5.1.2.

Packaged and unpackaged

According to Learn, the WinUI templates build an MSIX package by default: the application has a package identity, the manifest Package.appxmanifest, and Windows installs it as a package. Packaged is the recommended default. For Visual Studio it follows: start with the launch profile MsixPackage, not with the profile that calls the .exe directly. The packaging step installs the required runtime parts.

Unpackaged means: no MSIX, no package identity. There are two ways to bring the Windows App SDK runtime along:

  • Framework-dependent: the runtime has to be installed on the machine, and the application's installer takes care of that. If it is missing, Windows reports at startup the error "Unable to load DLL 'Microsoft.ui.xaml.dll'". According to Learn, this is the most common cause of that message: an unpackaged application on a machine without the matching runtime.
  • Self-contained: the application brings the Windows App SDK dependencies with it.

What lies in between (settings in the project file, distribution paths, consequences for updates and file associations) is the subject of W5.3.2. For the start, the difference is enough: packaged is the template's path, and the exercises run packaged.

XAML Hot Reload and the runtime tools

The reason why working on a user interface can be pleasant: you change XAML while the application is running, and you see the change without restarting. For WinUI 3, Visual Studio has four tools for this that work together:

Tool Purpose Where
XAML Hot Reload pushes changes to XAML into the running application automatic, as long as you edit a XAML file and the debugger is attached
Live Visual Tree shows the element tree of the running application and lets you select elements Debug, Windows, Live Visual Tree
Live Property Explorer shows and changes the properties of the selected element at runtime Debug, Windows, Live Property Explorer
XAML Live Preview shows the running application inside Visual Studio Debug, Windows, XAML Live Preview

The prerequisites and limits, according to Learn:

  • XAML Hot Reload needs the debugger. Start with F5; Ctrl+F5 (without debugging) turns off Hot Reload, the Live Visual Tree and the Live Property Explorer. The running application shows a small toolbar that confirms Hot Reload is available. If it is missing, check under Tools, Options, Debugging, XAML Hot Reload whether the option is turned on.
  • Hot Reload handles the usual changes: adding, removing or reordering elements, changing property values (colors, spacing, text, sizes), adding or changing styles and resources, changing the content of data templates.
  • According to Learn, these require a restart: new classes, new event handlers in the code-behind, changes to the x:Class, occasionally changes to the merged dictionaries in App.xaml, and x:Bind expressions that point to new properties. If Hot Reload cannot apply a change, the toolbar shows a message.
  • According to Learn, the designer (the "Design" tab with drag and drop) does not currently support WinUI 3 projects. A XAML file that shows only the XML editor is therefore not broken. The tools in the table exist for that. Learn also recommends the XAML Binding Failures window (Debug, Windows) for finding errors in bindings.
  • The winapp CLI does not have these tools; it builds and runs (winapp run). If you work with it, you change XAML, save and restart.

Learn suggests a playground page: a page of its own whose only purpose is to try out controls, styles and layouts. During development it can be reached through a menu item that appears only in debug builds (#if DEBUG). It is a good place for everything you try in W5.1.2 before it goes into a real page.

Exercise 1

Run the template. Create a throwaway project, run it and change the user interface once.

  1. In an empty folder outside the Kladde, create a project that you delete again after the exercise: in Visual Studio the template WinUI Blank App (Packaged) with the name WinUIProbe, or with the CLI winapp new --name WinUIProbe --template winui --use-defaults.
  2. Run the application (F5 or winapp run). A window opens.
  3. Close the application. Open MainPage.xaml (or MainWindow.xaml if the page does not exist) and add the TextBlock with "Hello, WinUI!" from the section above, without removing existing controls.
  4. Run it again.

How to check: the window shows the new text, in the center. If it does not appear, go through the table of observations.

Solution 1

The steps are described above. The most common reasons why the template does not start: a missing Developer Mode (the deployment reports it), a missing workload (the templates do not appear in Visual Studio), a wrong version of .NET SDK or winapp CLI. If you get a different error message, the cause is in the first lines of the build output. Read the first error, not the last one: the later ones are mostly consequences.

Cleaning up: close the application. A packaged project is registered as an app during deployment (Learn says that Developer Mode is needed to register the app from the output). After closing, look in the app list of Windows for an entry with the project name, and uninstall it like any other app; what the entries there are called, Learn does not say on the pages that were read. Then delete the folder WinUIProbe.

Exercise 2

Try Hot Reload. This exercise needs Visual Studio. With the winapp CLI, read it as a description and skip steps 2 to 4.

  1. Run WinUIProbe with the debugger (F5, not "without debugging"). Check whether the toolbar appears in the running application.
  2. In MainPage.xaml, change the text and the FontSize of the TextBlock and save. Observe whether the running application shows the change without a restart.
  3. Open Debug, Windows, Live Visual Tree. Select the TextBlock in the tree and open the Live Property Explorer. Change the outer spacing (Margin) there.
  4. In the XAML file, add a second button and give it an event handler Click="New_Click", which you create in the code-behind. Observe what happens when you let the change be applied.

How to check: steps 2 and 3 take effect without a restart. For step 4, Learn says that new event handlers in the code-behind require a restart. The toolbar may show a message about it.

Solution 2

Step 2: property values are part of what Hot Reload applies. Step 3: the Live Property Explorer changes only the running application, not your file. Remember this, otherwise you lose the change at the next start. Copy what you like into the XAML file. Step 4: a new handler is a change to the C# code, and XAML Hot Reload does not reload C# code. Restart. If Hot Reload shows nothing at all, check one after the other: is the debugger running (Ctrl+F5 turns Hot Reload off), is Enable XAML Hot Reload turned on, was the file saved, is there a message in the toolbar.

The page on the XAML runtime tools names a minimum release of Visual Studio for WinUI 3. Visual Studio itself shows which release you have under Help, About; compare it with the statement on Learn if the tools are missing in your installation.

Cleaning up: nothing except deleting the project at the end of the lesson.

Exercise 3

Assign the files. Without changing anything, answer four questions about your WinUIProbe project.

  1. In which file is the name of the target framework, and what is it? Does the project file contain UseWinUI and a reference to Microsoft.WindowsAppSDK?
  2. In which file is the window created, and in which method?
  3. Where do you change the name that Windows gives the application in the Start menu, and where the logo?
  4. Where would you enter a color that is supposed to apply in the whole application?

How to check: you find every place without searching. If not, open the file and read the lines.

Solution 3

  1. The project file (.csproj). Learn names net10.0-windows10.0.26100.0 as an example; your template may set a different Windows part. Check UseWinUI and Microsoft.WindowsAppSDK.
  2. In App.xaml.cs, in OnLaunched.
  3. The display name and the logos come from Package.appxmanifest (publisher, logos and further details that determine how the app appears in the Store and in the system); the logo files are in the folder Assets. Exactly what Visual Studio calls the fields in the manifest editor, Learn does not describe on the pages that were read; open the file with the manifest editor and read the labels.
  4. In App.xaml. Learn names it as the place for resources of the whole application. How you enter colors for the light and dark theme separately there is shown in W5.1.2.

Exercise 4

Create Kladde.Desktop. Create the project for the Kladde.

  1. Change into the main folder of your Kladde (where Kladde.slnx and the folder src are) and on into src.
  2. Create the project. With Visual Studio: a new project from WinUI Blank App (Packaged), name Kladde.Desktop, location src. With the CLI: winapp new --name Kladde.Desktop --template winui --use-defaults.
  3. Run the application. The empty template appears.
  4. In the TextBlock or in the window title property, put a visible note "Kladde" so that you know it is the right project. You change the display name of the app in W5.3.2, when it is about the package.
  5. Stop the application. Add src/Kladde.Desktop to the repository, in a branch feature/winui-app, with a commit message like feat(desktop): WinUI template as Kladde.Desktop.

How to check: the application starts and shows the template. git status shows src/Kladde.Desktop with the files of the template, but without the folders bin and obj. If they are there, add bin/ and obj/ to the .gitignore.

Solution 4

The command creates the directory src/Kladde.Desktop next to the K2 projects. Where the CLI puts the project was not described on the pages that were read: after the command, check whether src/Kladde.Desktop exists, and otherwise move the folder. The classes are in the namespace Kladde.Desktop. In this lesson you do not add the project to the solution file Kladde.slnx: how the application project, the library and the tests are built together is set by W5.2.1, when the first tests exist.

The name of the project is also the name of the namespace. It appears later in error messages, type names and in the package. So choose it now and do not change it in the middle of the course.

Cleaning up: delete WinUIProbe from exercises 1 to 3 (and remove the app from the app list of Windows beforehand, see solution 1).

The Kladde: a Windows program next to the web application

With this lesson the Kladde has a new project: src/Kladde.Desktop, a packaged WinUI application that shows an empty window. You do not change the projects from K2 (Kladde.Core, Kladde.Data, Kladde.Web and the others). The program will use the Kladde's web API, from W5.2.2; the Kladde's rules stay where they are. In W5.1.2 you build the first pages of your own: appointments and contacts, in a NavigationView, still with fixed sample data in the code and without MVVM, because MVVM comes up only in W5.2.1. Until then, logic sits in the code-behind, and the lesson says so each time, so that you can tidy it up later.

What you can do now

  • You explain what the Windows App SDK and WinUI 3 are, and how both relate to WPF, Windows Forms, UWP and .NET MAUI, and you know where existing WPF and Windows Forms programs are covered.
  • You set up the .NET 10 SDK, Visual Studio with the WinUI workload or the winapp CLI, and Developer Mode.
  • You create a WinUI template, run it, and assign App.xaml, MainWindow.xaml, Package.appxmanifest and the project file to their purposes.
  • You tell packaged from unpackaged and recognize the error that occurs when the runtime is missing.
  • You use XAML Hot Reload, the Live Visual Tree and the WinUI 3 Gallery with their limits, and you have created Kladde.Desktop.

Further reading