Walkthrough—Create a C# component with WinUI 3 controls, and consume it from a C++/WinRT app that uses the Windows App SDK
C#/WinRT provides support for authoring Windows Runtime components, including WinUI custom types and custom controls. These components can be consumed from either C# or C++/WinRT applications that use the Windows App SDK. We recommend using C#/WinRT v1.6.4 or later to author runtime components with NuGet packaging support.
For more details about the supported scenarios, refer to Authoring C#/WinRT components in the C#/WinRT GitHub repo.
This walkthrough demonstrates how to author a C# component with a custom WinUI 3 control, and how to consume that component from a C++/WinRT app, using the Windows App SDK project templates.
Prerequisites
This walkthrough requires the following tools and components:
- Visual Studio 2022
- .NET 6.0 SDK
- Windows App SDK VSIX (1.1 from the stable channel)
Author your C#/WinRT component using the Windows App SDK
Create a new C# library project using the Class Library (WinUI 3 in Desktop) template provided by the Windows App SDK. For this walkthrough, we've named the library project WinUIComponentCs, and the solution AuthoringWinUI.
Leave the Place solution and project in the same directory box unchecked (otherwise, the
packages
folder for the C++ application in the preceding section will end up interfering with the C# library project).Delete the
Class1.cs
file that's included by default.Install the latest Microsoft.Windows.CsWinRT NuGet package in your project.
i. In Solution Explorer, right-click on the project node, and select Manage NuGet Packages.
ii. Search for the Microsoft.Windows.CsWinRT NuGet package, and install the latest version.
Add the following properties to your library project:
<PropertyGroup> <CsWinRTComponent>true</CsWinRTComponent> </PropertyGroup>
- The
CsWinRTComponent
property specifies that your project is a Windows Runtime component so that a.winmd
file is generated when you build the project.
- The
Add a custom control or user control to your library. To do this, right-click on your project in Visual Studio, click Add > New Item, and select WinUI on the left pane. For this walkthrough, we added a new User Control (WinUI 3) and named it
NameReporter.xaml
. The NameReporter user control allows a user to enter a first and last name into the appropriate TextBox control, and click a button. The control then displays a message box with the name that the user entered.Paste the following code in the
NameReporter.xaml
file:<UserControl x:Class="WinUIComponentCs.NameReporter" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:WinUIComponentCs" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <StackPanel HorizontalAlignment="Center"> <StackPanel.Resources> <Style x:Key="BasicTextStyle" TargetType="TextBlock" BasedOn="{StaticResource BodyTextBlockStyle}"> <Setter Property="Margin" Value="10,10,10,10"/> </Style> </StackPanel.Resources> <TextBlock Text="Enter your name." Margin="0,0,0,10"/> <StackPanel Orientation="Horizontal" Margin="0,0,0,10"> <TextBlock Style="{StaticResource BasicTextStyle}"> First Name: </TextBlock> <TextBox Name="firstName" /> </StackPanel> <StackPanel Orientation="Horizontal" Margin="0,0,0,10"> <TextBlock Style="{StaticResource BasicTextStyle}"> Last Name: </TextBlock> <TextBox Name="lastName" /> </StackPanel> <Button Content="Submit" Click="Button_Click" Margin="0,0,0,10"/> <TextBlock Name="result" Style="{StaticResource BasicTextStyle}" Margin="0,0,0,10"/> </StackPanel> </UserControl>
Add the following method to
NameReporter.xaml.cs
:using System.Text; ... private void Button_Click(object sender, RoutedEventArgs e) { StringBuilder displayText = new StringBuilder("Hello, "); displayText.AppendFormat("{0} {1}.", firstName.Text, lastName.Text); result.Text = displayText.ToString(); }
You can now build the WinUIComponentCs project to generate a
.winmd
file for the component.
Note
You can also package the component as a NuGet package for end app consumers to reference. For more details, see Authoring C#/WinRT components on the C#/WinRT Github repo.
Reference the component from a Windows App SDK C++/WinRT app
The following steps show how to consume the component created from the previous section from a C++/WinRT Windows App SDK application. Consuming a C#/WinRT component from C++ currently requires using the single-project Blank App, Packaged (WinUI 3 in Desktop) template. Note that C# components can also be referenced from C# packaged apps without class registrations.
Consumption from packaged apps that use a separate Windows Application Packaging (WAP) project is not currently supported. See Authoring C#/WinRT components in the C#/WinRT GitHub repo for the latest updates on supported project configurations.
Add a new C++ Windows App SDK application project to your solution. Right-click on your solution in Visual Studio, and select Add > New Project. Select the C++ Blank App, Packaged (WinUI 3 in Desktop) template provided by the Windows App SDK. For this walkthrough, we named the app CppApp.
Add a project reference from the C++ app to the C# component. In Visual Studio, right-click on the C++ project and choose Add > Reference, and select the WinUIComponentCs project.
Note
Consuming components as a NuGet package reference is supported with some limitations. Namely, components with custom user controls can't currently be consumed as a NuGet package reference.
In the app's
pch.h
header file, add the following lines:#include <winrt/WinUIComponentCs.h> #include <winrt/WinUIComponentCs.WinUIComponentCs_XamlTypeInfo.h>
Open up the package manifest file,
Package.appxmanifest
.Note
There's a known issue where the
Package.appxmanifest
file doesn't appear in Visual Studio Solution Explorer. To workaround that, right-click on your C++ project, select Unload Project, and double-click on the project to open theCppApp.vcxproj
file. Add the following entry to the project file, and then reload the project:<ItemGroup> <AppxManifest Include="Package.appxmanifest"> <SubType>Designer</SubType> </AppxManifest> </ItemGroup>
In
Package.appxmanifest
, add the following activatable class registrations. You'll also need an additionalActivatableClass
entry for the WinUIComponentCs.WinUIComponentCs_XamlTypeInfo.XamlMetaDataProvider class in order to activate the WinUI types. Right-click on thePackage.appxmanifest
file and select Open With > XML (Text Editor) in order to edit the file.<!--In order to host the C# component from C++, you must add the following Extension group and list the activatable classes--> <Extensions> <Extension Category="windows.activatableClass.inProcessServer"> <InProcessServer> <Path>WinRT.Host.dll</Path> <ActivatableClass ActivatableClassId="WinUIComponentCs.NameReporter" ThreadingModel="both" /> <ActivatableClass ActivatableClassId="WinUIComponentCs.WinUIComponentCs_XamlTypeInfo.XamlMetaDataProvider" ThreadingModel="both" /> </InProcessServer> </Extension> </Extensions>
Open the
MainWindow.xaml
file.i. Add a reference to the component's namespace at the top of the file.
xmlns:custom="using:WinUIComponentCs"
ii. Add the user control to the existing XAML code.
<StackPanel> ... <custom:NameReporter/> </StackPanel>
Set CppApp as the startup project—right-click on CppApp, and select Set as Startup Project. Set the solution configuration to
x86
. Before building, you might also need to retarget your solution to build with the Visual Studio 2022 build tools. Right-click on the solution, select Retarget solution, and upgrade the Platform Toolset to v143.Build and run the app to see the custom NameReporter control.
Known issues
- Consuming a C# component as a project reference requires
PublishReadyToRun
to be set toFalse
. See Github Issue #1151 for more details. - Consuming a C# component built for
AnyCPU
from C++ is supported only fromx86
applications currently.x64
andArm64
apps result in a runtime error similar to: %1 is not a valid Win32 application. See Github Issue #1151 for more details.
Related topics
Windows developer