WinUI is a set of open source controls and libraries that Windows developers can leverage in their Universal Windows Platform (UWP) and Win32 applications. UWP developers use the Windows software development kit (SDK) to build their applications and are required to select a target SDK version in a project's properties. By extracting the UWP controls and user interface (UI) components from the Windows SDK and releasing them as a set of open source libraries under the name WinUI, Microsoft is able to release versions at a faster cadence than Windows itself (as Windows SDK versions are linked to those of Windows). This separation also enables the controls to be used on older versions of Windows 10. While building UWP and Win32 applications with WinUI is the current recommendation, it is important to learn where WinUI and UWP fit in the larger Windows development landscape.
In this book, you will learn how to build applications for Windows with the WinUI 3.0 libraries. Throughout the course of the book, we will build a real-world application using recommended patterns and practices for Windows application development.
Before we start building our WinUI app, it's important to have a good foundation in Windows client development, the different types of Extensible Application Markup Language (XAML) UI markup, and how WinUI compares to other Windows desktop development frameworks. Therefore, in this first chapter, you will start by learning some background on UWP and WinUI.
In this chapter, we will learn about the following topics:
Don't worry! It won't take very long to cover the background stuff, and it will help provide some context as you start building your WinUI app. In the next chapter, you will get your hands on some code when you create your first WinUI project.
To follow along with the examples in this chapter, the following software is required:
The source code for this chapter is available on GitHub at this URL: https://github.com/PacktPublishing/-Learn-WinUI-3.0/tree/master/Chapter01.
Note
The WinUI 3.0 site on Microsoft Docs has up-to-date guidance on setting up a developer workstation for WinUI development: https://docs.microsoft.com/en-us/uwp/toolkits/winui3/.
Before UWP applications were launched with Windows 10 in 2015, there were XAML applications for Windows 8 and 8.1. The XAML syntax and many of the application programming interfaces (APIs) were the same, and they were Microsoft's next step in an attempt to achieve universal app development across desktop, mobile, and other platforms (Xbox, mixed reality, and so on). A XAML app could be written for Windows 8 and Windows Phone. These projects would generate separate sets of binaries that could be installed on a PC or a Windows Phone.
These apps had many other limitations that modern UWP apps do not. For instance, they only ran fullscreen, as shown in the following screenshot:
Many other early restrictions on Windows 8 apps have been lessened or completely removed in UWP app development. Figure 1.2, which follows, documents these changes:
The term Metro Style was used to define the design and layout of Windows 8 apps. Metro Style apps were designed to be usable with touch input, mouse and keyboard, or a stylus. Microsoft's introduction of the first Windows Phone was a driving factor for Metro Style design. Metro Style later became Modern UI design, with the introduction of Surface devices. Aspects of Metro live on today, in UWP apps and Windows 10.
Live Tiles were born with Metro Style. These tiles on the user's Windows 8 home screen and Windows 10 Start menu can update to display live updates to users without having to open the app. Most of Microsoft's own apps for Windows support Live Tiles. The Weather app can show live updates to current weather conditions on the tile, based on the user's current location. You will explore Live Tiles further in Chapter 5, Exploring WinUI Controls and Libraries.
Another term that has its roots in Windows 8 app development is WinRT. The letters RT became a source of great confusion. WinRT was short for Windows Runtime, the underlying APIs used by Windows XAML apps. There was also a version of Windows 8 called Windows RT that supported Advanced RISC Machines (ARM) processors. The first Surface PC was the Surface RT, which ran the Windows 8 RT operating system.
Although WinRT can still be used today to define the WinRT APIs consumed by UWP apps, you will not see the term as often. We will also avoid using WinRT in this book and instead refer to the APIs as the UWP or Windows APIs.
While Microsoft pushed hard to win over users with Modern UI design, a new app model, Surface PCs, and Windows 8 and 8.1, the idea of a fullscreen, touch-first app experience and a deemphasized Windows desktop was never embraced by customers. It turns out that Windows users really like the start menu experience they used for years with Windows XP and Windows 7.
The next step in Windows app development was a big one—so big, in fact, that Microsoft decided to skip a number in their versioning, jumping straight from Windows 8.1 to Windows 10.
While taking a leap forward with the launch of Windows 10, Microsoft also blended the best of what worked in previous versions of Windows. They brought back the start menu, but its contents look an awful lot like the Windows 8 home screen experience. In addition to an alphabetized list of all installed apps, there is a resizable area for pinned app tiles. In fact, when running Windows in Tablet Mode, the start menu can transform into the Windows 8-style home screen experience for better usability on a touchscreen.
When Microsoft launched Windows 10, they also introduced UWP applications to Windows developers. While UWP apps have their roots in the XAML apps of Windows 8, there are some key differences that give developers some major advantages when building apps for the platform.
A key advantage is in the Universal aspect of these apps. Microsoft builds versions of Windows 10 to run on different device families, listed as follows:
UWP developers can build apps to target any of these devices. There is a single base set of Windows APIs shared across all these targets, and specialized SDKs available for the device-specific APIs of some families—for example, there is a Mixed Reality Toolkit and SDK for HoloLens development. With UWP, it is possible to create a single project to target many device families—for instance, you can create a project that creates apps for Desktop, Xbox, and Team families.
Because the UWP XAML for building the app's UI is the same, the learning curve for cross-device development is lowered and code reusability is very high. The nature of XAML provides a UI flexibility to adapt to different device sizes and aspect ratios.
While the underlying UWP APIs were written in C++, UWP developers can choose from a number of programming languages when building apps for Windows. UWP projects can be created with any of these popular languages:
You may be surprised to see JavaScript on the list. During the Windows 8.x days, developers could create JavaScript apps with APIs known as WinJS apps. Today, Microsoft has created a branch of React Native for Windows developers, known as React Native for Windows. These JavaScript client apps have full access to the same Windows APIs as other UWP apps and can be packaged and deployed through the Windows Store.
Note
React Native for Windows is an open source project hosted by Microsoft on GitHub at https://github.com/Microsoft/react-native-windows.
While many of the UWP apps developed for Windows 10 by Microsoft are created with C++, most other developers choose C#. We will also use C# when building our app throughout the course of this book.
As discussed earlier, apps built for Windows 8 had a number of restrictions that have been either removed or relaxed with UWP.
First and foremost, today's UWP apps can run in resizable windows, just like any other Windows desktop application. The trade-off is that developers now need to test for and handle the resizing of their app to almost any size. The dynamic nature of XAML can handle much of the resizing very well, but below a certain minimum size, scroll bars will need to be employed.
For end users, one of the benefits of using UWP apps is the inherent security they provide due to the limited access of apps to the PC's filesystem. By default, each app can only access its own local storage. In 2018, the Windows developer team announced a new feature for UWP developers. By adding some app configuration declaring which additional types of access the app requires, applications can request access to additional parts of the filesystem. Among them are the following:
Note
There are additional filesystem permissions that can be requested. See the Microsoft documentation for an entire list: https://docs.microsoft.com/en-us/windows/uwp/files/file-access-permissions.
Any additional permissions requested will be declared on the app's listing on the Windows Store.
Some less common scenarios are now available to UWP apps on Windows 10. Developers can add some configuration and startup code to enable multiple instances of their app to launch. While it would seem that the point of a UWP app is the XAML UI, it is now possible to create a UWP console app. The app will run at the command line and have access to Universal C runtime calls. Developers who want to get started with console apps can find project templates on Visual Studio Marketplace, at https://marketplace.visualstudio.com/items?itemName=AndrewWhitechapelMSFT.ConsoleAppUniversal.
No UWP app is compatible with any version of Windows before Windows 10. Beyond this, each UWP app must declare a Target Version and a Minimum Version of Windows with which it is compatible. The target version is your recommended version, which will enable all of an app's features and functionality. The minimum version is, unsurprisingly, the minimum version of Windows that users must have to be able to install an app from the Windows Store.
Visual Studio will prompt you to select these versions when creating a new UWP project. If the two are the same, it keeps things simple. You will have all of the APIs of that SDK version available to the app. If the target version is greater than the minimum version, you need to add some conditional code to light up the features of any versions greater than the minimum. The app must still be useful to users running the minimum version; otherwise, it is advisable to increase the minimum. If any of the newer APIs or controls are fundamental to the app, it is also recommended that the minimum version be increased to one where those are available.
Note
For more information on writing the conditional or version adaptive code, see the Microsoft documentation here: https://docs.microsoft.com/en-us/windows/uwp/debug-test-perf/version-adaptive-code.
If you are creating .NET libraries that will be referenced by your UWP project and you would like to share them across other platforms, perhaps by a Xamarin mobile app, a .NET Standard version should be targeted by the shared library project. The most common .NET Standard version today is .NET Standard 2.0. To reference a .NET Standard 2.0 project from a UWP project, the target version of the UWP project should be 16299 or later.
The primary benefit of WinUI over UWP is that it lessens the dependency of Windows apps on a particular version of Windows. Instead, the controls, styles, and APIs are maintained outside of the Windows SDK. As of this writing, the minimum version required for a WinUI 3.0 app is 17134 or higher, and the target version must be set to 18362 or higher. Check the latest WinUI documentation for the current minimum requirements.
The hope for WinUI is to bring a greater number of controls and features to more supported versions of Windows 10 as the project matures.
XAML is based on Extensible Markup Language (XML). This would seem like a great thing as XML is a flexible markup language familiar to most developers. It is indeed flexible and powerful, but it has some drawbacks.
The primary problem with Microsoft's implementations of XAML is that there have been so many variations of the XAML language created for different development platforms over the years. Currently, UWP, Windows Presentation Foundation (WPF), and Xamarin.Forms applications all use XAML as their UI markup language. However, each of these uses a different XAML implementation or schema, and the markup cannot be shared across the platforms. In the past, Windows 8, Silverlight, and Windows Phone apps also had other different XAML schemas.
If you have never worked with XAML before, you're probably ready to see an example of some UI markup. The following XAML is a fragment that defines a Grid containing several other of the basic WinUI controls (you can download the code for this chapter from GitHub here: https://github.com/PacktPublishing/-Learn-WinUI-3.0/tree/master/Chapter01):
<Grid Width="400" Height="250" Padding="2"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0"
Text="Name:"
Margin="0,0,2,0"
VerticalAlignment="Center"/>
<TextBox Grid.Row="0" Grid.Column="1"
Text=""/>
<Button Grid.Row="1" Grid.Column="1" Margin="0,4,0,0"
HorizontalAlignment="Right"
VerticalAlignment="Top"
Content="Submit"/>
</Grid>
Let's break down the XAML here. The top level of a UWP window is Page. UWP app navigation is page-based, and this top-level navigation happens within a root Frame container in the App.xaml file in the project. You will learn more about page navigation in Chapter 4, Advanced MVVM Concepts. A Page must contain only one child, usually some type of layout panel such as a Grid or StackPanel. By default, a Grid is inserted as that child. We will discuss other types of panels that serve as a good parent container in the next chapter. I made a few modifications to the Grid.
Height and Width properties provide a static size for the example, and HorizontalAlignment and VerticalAlignment properties will center the Grid on the Page. Fixed sizes are uncommon at this level of the XAML and limit the flexibility of the layout, but they illustrate some of the available attributes.
A Grid is a layout panel that allows developers to define rows and columns to arrange its elements. The rows and columns can have their sizes defined as fixed, relative to each other, or auto-sized based on their contents. For more information, you can read the Microsoft Docs article Responsive layouts with XAML: https://docs.microsoft.com/en-us/windows/uwp/design/layout/layouts-with-xaml.
The Grid.RowDefinitions block defines the number and behavior of the grid's rows. Our grid will have two rows. The first one has Height="Auto", which means it will resize itself to fit its contents, provided enough space is available. The second row has Height="*", which means the rest of the grid's vertical space will be allocated to this row. If multiple rows have their height defined like this, they will evenly split the available space. We will discuss additional sizing options in the next chapter.
The Grid.ColumnDefinitions block does for the grid's columns what RowDefinitions did for the rows. Our grid has two columns defined. The first ColumnDefinition has its Height set to Auto, and the second has Height="*".
TextBlock defines a label in the first Grid.Row and Grid.Column. When working with XAML, all indexes are 0-based. In this case, the first Row and Column are both at position 0. The Text property conveniently defines the text to display, and the VerticalAlignment in this case will vertically center the text for us. The default VerticalAlignment for a TextBlock is Top. The Margin property adds some padding around the outside of the control. A margin with the same amount of padding on all sides can be set as a single numeric value. In our case, we only want to add a couple of pixels to the right side of the control to separate it from TextBox. The format for entering these numeric values is "<LEFT>,<TOP>,<RIGHT>,<BOTTOM>", or "0,0,2,0" here.
The TextBox is a text entry field defined in the second column of the grid's first row.
Finally, we've added a Button control to the second column of the grid's second row. A few pixels of top margin are added to separate it from the controls above. The VerticalAlignment is set to Top (the default is Center) and HorizontalAlignment is set to Right (the default is Center). To set the text of the Button, you don't use the Text property like we did with the TextBlock, as you might think. In fact, there is no Text property. The Content property of the Button is used here. Content is a special property that we will discuss in more detail in the next chapter. For now, just know that a Content property can contain any other control: text, an Image, or even a Grid control containing multiple other children. The possibilities are virtually endless.
Here is the UI that gets rendered by the preceding markup:
This is a very simple example to give you a first taste of what can be created with XAML. As we move ahead, you will learn how powerful the language can be.
In the previous example, the Grid had fixed Height and Width properties. I mentioned that setting fixed sizes can limit a UI's flexibility. Let's remove the fixed size properties and use the alignment properties to guide the UI elements, to render how we want them to at different sizes and aspect ratios, as follows:
<Grid VerticalAlignment="Top" HorizontalAlignment="Stretch" Padding="2">
The rest of the markup remains unchanged. The result is a TextBox that resizes to fit the width of the window, and the Button remains anchored to the right of the window as it resizes. See the window resized a couple of different ways here:
If you were using this app on a tablet PC, the contents would resize themselves to fit in the available space. That is the power of XAML's adaptive nature. When building a UI, you will usually want to choose relative and adaptive properties such as alignment to fixed sizes and positions.
It's this adaptive layout that makes XAML work so well on mobile devices with Xamarin, and this is why WPF developers have loved using it since its launch with Windows Vista.
Another reason why UWP and other XAML-based frameworks are so popular is the ease and power of their data-binding capabilities. Nearly all properties on UWP controls can be data-bound. The source of the data can be an object or a list of objects on the data source. In most cases, that source will be a ViewModel class. Let's have a very quick look at using UWP's Binding syntax for data binding to a property on a ViewModel class, as follows:
public class MainViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler
PropertyChanged;
private string _name;
public MainViewModel()
{
_name = "Bob Jones";
}
public string Name
{
get
{
return _name;
}
set
{
if (_name == value) return;
_name = value;
PropertyChanged?.Invoke(this, new
PropertyChangedEventArgs(nameof(Name)));
}
}
}
The MainViewModel class implements an interface called INotifyPropertyChanged. This interface is key to the UI receiving updates when data-bound properties have changed. This interface implementation is typically wrapped either by a Model-View-ViewModel (MVVM) framework, such as Prism or MvvmCross, or with your own ViewModelBase class. For now, we will directly invoke a PropertyChanged event inside the Name property's setter. We will learn more about ViewModels and the INotifyPropertyChanged interface in Chapter 3, MVVM for Maintainability and Testability.
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
this.ViewModel = new MainViewModel();
}
public MainViewModel ViewModel { get; set; }
}
We have added a ViewModel property to the MainPage and set it to a new instance of our MainViewModel class in the constructor.
Tip
Any code added to a page's constructor should be added after the call to InitializeComponent().
<TextBox Grid.Row="0" Grid.Column="1" Text="{x:Bind
Path=ViewModel.Name, Mode=TwoWay}"/>
Some markup has been added to set the Text property using the x.Bind markup extension. The data-binding Path is set to the Name property on the ViewModel, which has been assigned in the code-behind file in the preceding Step 2. By setting the data-binding mode to TwoWay, updates in the ViewModel will display in the UI, and any updates by the user in the UI will also be persisted in the Name property of the MainViewModel class. Now, running the app will automatically populate the name that was set in the constructor of the ViewModel, as illustrated in the following screenshot:
<Grid x:Name="ParentGrid"
VerticalAlignment="Top"
HorizontalAlignment="Stretch"
Padding="2">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="1" Grid.Column="0"
Text="Actual Width:"
Margin="0,0,2,0"
VerticalAlignment="Center"/>
<TextBlock Grid.Row="1" Grid.Column="1"
Text="{Binding ElementName=ParentGrid,
Path=ActualWidth}"/>
The Submit button does not function yet. You will learn how to work with Events and Commands with MVVM in Chapter 5, Exploring WinUI Controls and Libraries.
When working with XAML, styles can be defined and applied at almost any scope, global to the application in App.xaml, in the current Page inside a Page.Resources declaration, or inside any level or nested control on the page. The Style property specifies a TargetType property, which is the data type of the elements to be targeted by the style. It can optionally have a Key property defined as a unique identifier, similar to a class identifier in Cascading Style Sheets (CSS). That Key property can be used to apply the style to only selected elements of that type. Only one Key property can be assigned to an element, unlike with CSS classes.
In the next example, we will modify the page to define a Style property for all buttons on the page, as follows:
<StackPanel Grid.Row="1" Grid.Column="1"
Margin="0,4,0,0"
HorizontalAlignment="Right"
VerticalAlignment="Top"
Orientation="Horizontal">
<Button Content="Submit" Margin="0,0,4,0"/>
<Button Content="Cancel"/>
</StackPanel>
A new margin has been added to the first button to add some space between the elements.
<Page.Resources>
<Style TargetType="Button">
<Setter Property="BorderThickness"
Value="2" />
<Setter Property="Foreground"
Value="LightGray" />
<Setter Property="BorderBrush"
Value="GhostWhite"/>
<Setter Property="Background"
Value="DarkBlue" />
</Style>
</Page.Resources>
If we moved the Style block to the Application.Resources section, the defined style would get applied to every button in the entire app unless the developer had individually overridden some of the properties in the style. For instance, if the Submit button had a Background property set to DarkGreen, only the Cancel button would appear as dark blue.
We will spend more time on styles and design in Chapter 7, Windows Fluent UI Design.
We looked briefly at the MVVM pattern in the earlier section on data binding. MVVM is key to the separation of presentation logic from business logic in UWP application development. The XAML elements only need to know that there is a property with a particular name somewhere in its data context. The ViewModel classes have no knowledge of the View (our XAML file).
This separation provides several benefits. First, ViewModels can be unit tested independently of the UI. If any UWP elements are referenced by the system under test, the UI thread is needed. This will cause tests to fail when they're running on background threads locally or on a Continuous Integration (CI) server. See Chapter 3, MVVM for Maintainability and Testability for more information on unit testing WinUI applications.
The next benefit of View/ViewModel separation is that businesses with dedicated user experience (UX) experts will sometimes work on designing the XAML markup for an app while other developers are building the ViewModels. When it is time to sync up the two, the developer can add in the necessary data-binding properties to the XAML, or perhaps the UX designer and developer have already agreed upon the names of the properties in the shared data context. Visual Studio includes another tool geared toward designers in this workflow, called Blend for Visual Studio. Blend was first released by Microsoft in 2006 as Microsoft Expression Blend, as a tool for designers to create UIs for WPF. Support was later added for other XAML languages such as Silverlight and UWP. Blend is still included with the UWP development workload when installing Visual Studio.
A final benefit we will discuss here is that a good separation of concerns between any layers of your application will always lead to better maintainability. If there are multiple components involved in a single responsibility or if logic is duplicated in multiple places, this leads to buggy code and unreliable applications. Follow good design patterns, and you will save yourself a lot of work down the road.
Now that you have a good understanding of the history of UWP applications, it's time to look at WinUI: what it is, and why it was created.
The WinUI library is a set of controls and UI components that have been extracted from the Windows SDK. After this separation, many controls have been enhanced and others have been added. The libraries have been made available as open source on GitHub and are maintained by Microsoft and the Windows developer community.
So, if these WinUI libraries came from UWP libraries in the Windows SDK, you may be wondering why you should choose WinUI as your UI framework instead of UWP. UWP has been around since the launch of Windows 10 and is quite robust and stable. There are actually several very good reasons to consider WinUI.
Choosing WinUI brings with it all the benefits of open source. Open source software (OSS) is typically very reliable. When software is developed in the open by an active developer community, issues are found and resolved quickly. In fact, if you find an issue with an open source package, you can fix it yourself and submit a pull request to have the fix made available to the rest of the community. Open source projects can iterate quickly without having to remain in sync with product groups in a large enterprise such as the Windows team. Windows releases feature updates on a regular cadence now, but this is still less frequent than with a typical control library.
The best reason to use WinUI is its backward compatibility. When using a UWP control, the features and fixes in a specific version of the control cannot be deployed in apps to older versions of Windows. With WinUI, so long as you are targeting the minimum version of Windows supported by WinUI as a whole, you can use those new controls and features in multiple Windows versions. Controls not previously available to UWP developers on one version of Windows are now available there as WinUI controls.
For instance, Microsoft did not introduce the Fluent UI design to Windows until the Fall 2017 release (version 16299). However, WinUI controls can be included in apps targeting a minimum Windows version of 10.0.15063.0, the Spring 2017 release. The controls in WinUI support Fluent UI styles. WinUI adds controls and other features that are not available at all in UWP and the Windows SDK.
The first version of WinUI was released in July 2018 as a preview release for Windows developers. It was released as the following two NuGet packages:
3 months later, WinUI 2.0 was released. Despite the version number, it was the first production release of WinUI. The release included more than 20 controls and brushes. A few notable controls included the following:
Let's add a few of these controls to our WinUI project and see how they look. Change the contents of the StackPanel to look like this:
<StackPanel Grid.Row="1" Grid.Column="1" Margin="0,4,0,0"
HorizontalAlignment="Right"
VerticalAlignment="Top"
Orientation="Horizontal">
<PersonPicture Initials="MS" Margin="0,0,8,0"/>
<DropDownButton Content="Submit" Margin="0,0,4,0">
<DropDownButton.Flyout>
<MenuFlyout Placement="Bottom">
<MenuFlyoutItem Text="Submit + Print"/>
<MenuFlyoutItem Text="Submit + Email"/>
</MenuFlyout>
</DropDownButton.Flyout>
</DropDownButton>
<Button Content="Cancel"/>
</StackPanel>
A PersonPicture control with the initials MS has been added as the first item in the StackPanel, and the first of the two buttons has been replaced by a DropDownButton control. The Submit DropDownButton control has a FlyoutMenu serving as a drop-down list, and there are two MenuFlyoutMenuItem elements. Now, users can simply click the Submit button, or they can select Submit + Print or Submit + Email from the drop-down list.
Note
DropDownButton is only available in Windows 10 version 1809 and later. If you use this control in a production application, you should set this as your minimum version for the project.
This is how the new window appears with the DropDownButton menu shown:
We're only scratching the surface of what the first release can do for Windows developers. Don't worry, as we will dive much deeper in the chapters ahead. Let's briefly look at what was added in subsequent versions leading to WinUI 3.0.
There have been five additional minor releases of WinUI following v2.0, in addition to many incremental bug fixes and prerelease versions.
The WinUI 2.1 release brought a number of new controls and features to the library. These are some highlights:
Note
Get more information about Lottie files on their website at https://airbnb.design/lottie/ and check out this great repository of Lottie animation files: https://lottiefiles.com/
This release brought many enhancements to existing features. However, the single new control added to the library is one that many Windows developers will find useful.
The TabView control creates a familiar tabbed user experience on the screen. Each tab can host a page in your WinUI project.
A few of the notable updated controls and libraries in version 2.2 are listed here:
In the WinUI 2.3 release, the ProgressBar received some updates, and a couple of new controls were added to the library.
There are now two modes available when creating a Progress Bar in a WinUI application: Determinate and Indeterminate. A determinate progress bar has a known amount of the task to complete and a known current state of the task. An indeterminate control indicates that a task is ongoing without a known completion time. Its purpose to similar to that of a busy indicator.
The following are a few new controls in this update:
When it was released in May 2020, two new features were made available in WinUI 2.4: a RadialGradientBrush visual and a ProgressRing control.
The brush is similar in use to the RadialGradientBrush used by WPF developers. It makes it easy to add a gradient to a visual element that radiates out from a central point.
The ProgressRing control, as it sounds, recreates progress bar functionality in a circular format. The control is available with a determinate state and an indeterminate state in version 2.4. An indeterminate ProgressRing control displays a repeating animation and is the default state of the control.
Several controls were updated in version 2.4. The TabView control was updated to provide more control over how tabs are rendered, including Compact, Equal, and Size to Content modes. TextBox controls received a dark mode enhancement to keep the content area of the control dark, with white text by default. Finally, the NavigationView control was updated with hierarchical navigation, with Left, Top, and LeftCompact modes.
WinUI 2.5 was released in December 2020 and included a new InfoBar control. Several control enhancements and bug fixes were also included in the release.
The InfoBar control provides a way to display important status messages to users. The control can display an alert or informational icon, a status message, and a link or button allowing users to take action on a message. There is also an option to display a close button to the right of the message. By default, the control includes an icon, message, and close button. Microsoft Docs provides usage guidelines for this new control: https://docs.microsoft.com/en-us/windows/uwp/design/controls-and-patterns/infobar.
Several updates are also available in version 2.5. The ProgressRing control received enhancements to the determinate state of the control. The NavigationView control was updated to provide customizable FooterMenuItems. In previous versions of the NavigationView control, the footer area could be shown or hidden but not customized.
We've seen what was available to UWP developers in WinUI 2.x. Now, let's see what you get with WinUI 3.0.
Unlike WinUI 2.0 and the incremental versions that followed, WinUI 3.0 is a major update featuring more than new and improved controls and libraries to use with UWP and .NET 5 apps. In fact, the primary goal of WinUI 3.0 was not to add new controls and features beyond its current UWP counterparts. For version 3.0, the team has made WinUI a complete UI framework that can sit atop the UWP or Win32 application platforms.
So, what is happening to UWP? Will my UWP apps stop working?
As previously mentioned, the plan for the UWP UI libraries is to keep providing important security updates, but they will not receive any new features going forward. All new features and updates will be developed for WinUI. New WinUI projects will support all types of Windows UI client. For existing Win32 applications, developers can incrementally upgrade parts of an application to WinUI with the Xaml Islands interop control. New applications will be developed in WinUI with either .NET Core, written in C# or VB, or with native C++. These clients will sit on top of either the Win32 platform or UWP. This is all possible because WinUI is developed completely in C++.
Note
Some features discussed in this book will not be available in the first stable Release To Manufacturing (RTM) version of WinUI 3.0, coming in March 2021 with Project Reunion v0.5. XAML Islands will not be available and UWP clients will not be fully supported initially. For a full list of what is planned for the first stable release of WinUI 3.0, you can reference the team's roadmap on GitHub: https://github.com/microsoft/microsoft-ui-xaml/blob/master/docs/roadmap.md#winui-30-feature-roadmap.
The fact that WinUI is developed in C++ enables React Native for Windows client apps to interoperate with the WinUI platform. Between React Native and the Uno Platform, WinUI has some great cross-platform potential.
Let's look at this new app model in the following screenshot:
As you can see, there will be multiple paths available for developers to create apps for Windows PCs and tablet devices such as the dual-screen Surface Duo. Other Windows devices, such as Xbox and HoloLens, will need to follow the UWP app model under the WinUI layer.
Are there any new features in WinUI 3.0?
While it sounded like the team was so busy creating a UI framework to replace the UWP UI libraries, they did find some time to add a few new features. The major new control available in version 3.0 is the new WebView2 control based on the Microsoft Edge Chromium browser. Compatibility is also a feature. All XAML and Composition features available in the Spring 2019 Windows SDK will be backward-compatible, back to the Windows Creators update and later.
WinUI 3.0 is bringing UWP and Win32 application developers together on a single set of UI libraries, but that is only the beginning. At Microsoft's Build 2020 conference, the Windows team announced Project Reunion, a long-term plan for bringing all Windows developers together on a single platform. WinUI 3.0 is focused on the UI layer, while Project Reunion will encompass WinUI and the entire Windows developer platform. In 2021, Microsoft will release three versions of Project Reunion and WinUI 3.x, as follows:
To read more about Project Reunion and to follow its progress, you can check out their GitHub repository at https://github.com/microsoft/ProjectReunion. Now, let's see how WinUI compares to other Windows development frameworks.
Where does WinUI fit in the overall landscape of Microsoft's Windows development frameworks? Let's draw some comparisons to help answer that question, starting with those that are most similar to WinUI.
This is a tricky comparison because most WinUI apps today are UWP apps at their core. In fact, WinUI 2.x are controls for UWP applications. When considering WinUI 3.0, think of WinUI as the UI framework and UWP as the application platform layer. They share the same XAML schema, base visuals, and underlying Windows APIs. Any UWP app that has the same minimum and target versions of Windows specified can add the WinUI 2.x libraries to leverage the new and updated features.
A key difference between apps that use WinUI versus traditional UWP apps is access to new and updated controls and other visual elements without requiring an updated Windows SDK. This enables developers to bring apps with the same look and features to more users across multiple versions of Windows 10. This differentiator makes for happier developers and users.
WinUI and WPF have many similarities. Both are application frameworks, and both types of apps rely on XAML to define UI elements. This means that they both offer the same separation of UI and business logic when implementing the MVVM pattern. WPF XAML has the same concepts of styles, resources, data binding, and adaptiveness of the UI layout.
A significant performance advantage of WinUI—and UWP apps in general—is the availability of compiled bindings. We will discuss compiled bindings in more detail later. For now, just know that using them offers a performance boost over traditional data binding in both UWP and WPF. Compiled bindings are identified by the use of the x:Bind syntax in XAML, rather than Binding.
Another advantage of WinUI over WPF is that it is more secure by default. Sandboxed access to users' filesystems and devices can give users a sense of ease, knowing that malicious behavior has limits to which hardware and data it can access. WPF apps' access is only limited by the configuration of Windows User Account Control (UAC) on the PC.
The primary advantage of WPF applications is the fact that they are not directly tied to minimum versions of Windows 10. WPF apps target a .NET Framework or .NET Core version. Any version of Windows that supports the target .NET version can run that WPF app. This significantly increases the potential user base of WPF apps. In fact, WPF apps can be deployed and run on Windows 7, something not possible with UWP or WinUI.
Note
There is a project called Uno Platform that enables WinUI XAML to run on iOS and Android, leveraging Xamarin and on the web with WebAssembly. These WinUI web apps can run in the browser on previous versions of Windows, including Windows 7. The Uno Platform goal and tagline is WinUI Everywhere.
Learn more about Uno Platform at https://platform.uno/.
Learn more about WebAssembly at https://webassembly.org/.
The secure-by-default nature of WinUI apps provides WPF apps with a greater degree of flexibility and power. Many types of applications will require full access to the Windows filesystem or to particular devices and drivers—for example, it would be much easier to create a custom file manager application with complete access to a computer's filesystem. While WinUI apps can now request this access in newer versions of Windows 10, this is available by default in any version with WPF.
A new WPF advantage emerged with the releases of .NET Core 3.x and .NET 5. .NET developers can now create WPF apps with .NET Core, bringing performance and deployment advantages of .NET Core to WPF developers. For instance, applications targeting difference versions of .NET Core can be deployed side by side on a machine without creating version conflicts.
The difference in deployment models can be debated as to which framework has an advantage. The easiest way to deploy a WinUI app is through the Windows Store. The easiest way to deploy a WPF app with .NET Framework is via an installer package. WPF apps can be deployed through the Store through Windows Containers, and WinUI apps can be deployed without the Store with MSIX installers. WinUI deployment will be covered in detail in Chapter 12, Build, Release, and Monitor Apps with Visual Studio App Center and Chapter 13, Packaging and Deployment Options and the Windows Store.
WinForms is a .NET UI framework that was introduced with .NET Framework 1.0. Developers can easily create a WinForms UI with the visual design surface in Visual Studio, which generates C# or VB code that creates the UI at runtime. Most of the advantages and disadvantages of WPF also apply to WinForms: security, deployment, and .NET Core—WinForms apps can also be created with .NET Core 3 and later.
Similarities between WinUI and WPF are their primary advantages over WinForms: data binding, adaptive layout, and a flexible styling model. These advantages all stem from the use of XAML for UI layout. Another advantage of XAML is offloading render processing from the central processing unit (CPU) to the graphics processing unit (GPU). WinUI controls inherit the Windows 10 styles by default and have a more modern appearance than WinForms controls. WinUI applications also handle dots per inch (DPI) scaling and touch input well. The WinForms UI framework matured before touch input and DPI scaling were a concern for Windows developers.
A primary advantage of WinUI over WPF also applies to WinForms: security by default.
In addition to the advantages that WinForms shares with WPF over WinUI—greater access to Windows, .NET Core apps, and Windows compatibility—WinForms also has a well- deserved reputation for rapid UI development. If you need to create a simple Windows application in a minimal amount of time, the drag-and-drop WinForms designer is easy and intuitive. Many experienced Windows developers still default to WinForms when tasked with creating a simple utility or UI test harness for a .NET library.
We have covered a lot of the history of Windows application development in this chapter. We learned about the origins of UWP and its roots in Windows 8 apps, and learned of the benefits of XAML when building Windows UIs. We had a taste of what some simple WinUI app code and UIs look like. Finally, we examined the recent history of WinUI versions and how the new version 3.0 is a complete replacement for the UWP UI libraries and a viable option for WPF developers going forward.
This will give you a good foundation of what's to come as we start building an app with WinUI in the chapters ahead. In the next chapter, you will set up your development environment, learn about the app project that we will create throughout the book, and create your first WinUI 3.0 project. When we get to Chapter 3, MVVM for Maintainability and Testability, we will refactor the app to use the MVVM pattern. This will set us up with a solid, maintainable design as we later add to and extend the app throughout the rest of the book.
18.225.11.98