Exemplarische Vorgehensweise: Erstellen einer C#-Komponente mit WinUI 3-Steuerelementen und Verwenden dieser aus einer C++/WinRT-App, die das Windows App SDK nutzt

C#/WinRT unterstützt die Erstellung von Komponenten für Windows-Runtime, einschließlich benutzerdefinierter WinUI-Typen und benutzerdefinierter Steuerelemente. Diese Komponenten können von C#- oder C++/WinRT-Anwendungen verwendet werden, die die Windows App-SDK verwenden. Es wird empfohlen, C#/WinRT v1.6.4 oder höher zu verwenden, um Laufzeitkomponenten mit NuGet-Paketunterstützung zu erstellen.

Weitere Details zu den unterstützten Szenarien finden Sie unter Erstellen von C#/WinRT-Komponenten im C#/WinRT-GitHub-Repo.

In dieser exemplarischen Vorgehensweise wird veranschaulicht, wie Sie eine C#-Komponente mit einem benutzerdefinierten WinUI 3-Steuerelement erstellen und diese Komponente aus einer C++/WinRT-App mithilfe der Windows App-SDK-Projektvorlagen verwenden.

Voraussetzungen

Für diese exemplarische Vorgehensweise werden folgende Tools und Komponenten benötigt:

Erstellen Sie Ihre C#/WinRT-Komponente mithilfe der Windows App SDK

  1. Erstellen Sie ein neues C#-Bibliotheksprojekt mithilfe der Vorlage Klassenbibliothek (WinUI 3 in Desktop), die von der Windows App-SDK bereitgestellt wird. Für diese exemplarische Vorgehensweise haben wir das Bibliotheksprojekt WinUIComponentCs und die Lösung AuthoringWinUI benannt.

    Lassen Sie die Projektmappe und das Projekt in demselben Verzeichnisfeld deaktiviert (andernfalls wird der Ordner packages für die C++-Anwendung im vorherigen Abschnitt dazu führen, dass das C#-Bibliotheksprojekt beeinträchtigt wird).

    New library dialog

  2. Löschen Sie die Class1.cs-Datei, die standardmäßig enthalten ist.

  3. Installieren Sie das neueste Microsoft.Windows.CsWinRT NuGet-Paket in Ihrem Projekt.

    i. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf den Projektknoten, und wählen Sie NuGet-Pakete verwalten aus.

    ii. Suchen Sie nach dem NuGet-Paket Microsoft.Windows.CppWinRT, und installieren Sie die neueste Version davon.

  4. Fügen Sie dem Bibliotheksprojekt die folgenden Eigenschaften hinzu:

    <PropertyGroup>   
        <CsWinRTComponent>true</CsWinRTComponent>
    </PropertyGroup>
    
    • Die CsWinRTComponent-Eigenschaft gibt an, dass Ihr Projekt eine Windows-Runtime-Komponente ist, sodass eine .winmd-Datei generiert wird, wenn Sie das Projekt entwickeln.
  5. Fügen Sie Ihrer Bibliothek ein benutzerdefiniertes Steuerelement oder benutzerspezifisches Steuerelement hinzu. Klicken Sie dazu mit der rechten Maustaste auf Ihr Projekt in Visual Studio, klicken Sie auf Neues Element>hinzufügen und wählen Sie WinUI im linken Bereich aus. Für diese exemplarische Vorgehensweise wurde ein neues Benutzersteuerelement (WinUI 3) hinzugefügt und NameReporter.xaml benannt. Das Benutzersteuerelement NameReporter ermöglicht es einem Benutzer, einen Vornamen und Nachnamen in das entsprechende TextBox-Steuerelement einzugeben und auf eine Schaltfläche zu klicken. Das Steuerelement zeigt dann ein Meldungsfeld mit dem Namen an, den der Benutzer eingegeben hat.

  6. Fügen Sie den folgenden Code in die NameReporter.xaml-Datei ein:

    <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>
    
  7. Fügen Sie NameReporter.xaml.cs zur folgenden Methode hinzu:

    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();
    }
    
  8. Sie können nun das WinUIComponentCs-Projekt erstellen, um eine .winmd-Datei für die Komponente zu erzeugen.

Hinweis

Sie können die Komponente auch als NuGet-Paket für App-Endbenutzer verpacken, um darauf zu verweisen. Weitere Details finden Sie unter Erstellen von C#/WinRT-Komponenten im C#/WinRT-Github-Repo.

Verweisen Sie auf die Komponente aus einer Windows App-SDK-C++/WinRT-App

In den folgenden Schritten wird gezeigt, wie Sie die Komponente verwenden, die aus dem vorherigen Abschnitt aus einer C++/WinRT-Windows App SDK-Anwendung erstellt wurde. Die Verwendung einer C#/WinRT-Komponente von C++ erfordert derzeit die Verwendung der Einzelprojekt-Vorlage Leere App, Gepackt (WinUI 3 in Desktop). Beachten Sie, dass C#-Komponenten auch von C#-gepackten Apps ohne Klassenregistrierungen verwiesen werden können.

Verbrauch von gepackten Apps, die ein separates WAP-Projekt (Windows Application Packaging) verwenden, wird derzeit nicht unterstützt. Siehe Erstellen von C#/WinRT-Komponenten in C#/WinRT-GitHub-Repo für die neuesten Updates für unterstützte Projektkonfigurationen.

  1. Fügen Sie Ihrer Lösung ein neues C++-Windows App-SDK-Anwendungsprojekt hinzu. Klicken Sie mit der rechten Maustaste auf Ihre Lösung in Visual Studio, und wählen Sie Neues Projekt>hinzufügen aus. Wählen Sie die C++-Vorlage Leere App, Gepackt (WinUI 3 in Desktop)aus, die vom Windows App-SDK bereitgestellt wird. Für diese exemplarische Vorgehensweise wurde die App CppApp genannt.

  2. Fügen Sie einen Projektverweis aus der C++-App zur C#-Komponente hinzu. Klicken Sie in Visual Studio mit der rechten Maustaste auf das C++-Projekt, und wählen Sie Verweis >hinzufügen aus und wählen Sie das WinUIComponentCs-Projekt aus.

    Hinweis

    Die Verwendung von Komponenten als NuGet Paketverweis wird mit einigen Einschränkungen unterstützt. Die Komponenten mit benutzerdefinierten Benutzersteuerelementen können derzeit nicht als NuGet-Paketverweis verwendet werden.

  3. Fügen Sie in der Headerdatei pch.h der App die folgenden Zeilen hinzu:

    #include <winrt/WinUIComponentCs.h>
    #include <winrt/WinUIComponentCs.WinUIComponentCs_XamlTypeInfo.h>
    
  4. Öffnen Sie die Paketmanifestdatei, Package.appxmanifest.

    Hinweis

    Es gibt ein bekanntes Problem, bei dem die Package.appxmanifest-Datei nicht im Visual Studio Projektmappen-Explorer angezeigt wird. Um das zu umgehen, klicken Sie mit der rechten Maustaste auf Ihr C++-Projekt, wählen Sie Projekt entladen und doppelklicken Sie auf das Projekt, um die CppApp.vcxproj-Datei zu öffnen. Fügen Sie den folgenden Eintrag zur Projektdatei hinzu und laden Sie das Projekt dann neu:

    <ItemGroup>
        <AppxManifest Include="Package.appxmanifest">
        <SubType>Designer</SubType>
        </AppxManifest>
    </ItemGroup>
    

    Fügen Sie in Package.appxmanifest, die folgenden aktivierungsfähigen Klassenregistrierungen hinzu. Sie benötigen auch einen zusätzlichen ActivatableClass Eintrag für die WinUIComponentCs.WinUIComponentCs_XamlTypeInfo.XamlMetaDataProvider-Klasse, um die WinUI-Typen zu aktivieren. Klicken Sie mit der rechten Maustaste auf die Package.appxmanifest-Datei und wählen Sie Mit>XML öffnen (Text-Editor) aus, um die Datei zu bearbeiten.

    <!--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>
    
  5. Öffnen Sie die Datei MainWindow.xaml.

    i. Fügen Sie oben in der Datei einen Verweis auf den Namespace der Komponente hinzu.

    xmlns:custom="using:WinUIComponentCs"
    

    ii. Fügen Sie dem vorhandenen XAML-Code das Benutzersteuerelement hinzu.

    <StackPanel>
        ...
        <custom:NameReporter/>
    </StackPanel>
    
  6. Legen Sie CppApp als Startprojekt fest – klicken Sie mit der rechten Maustaste auf CppApp und wählen Sie Als Startprojekt festlegen aus. Legen Sie die Projektmappenkonfiguration fest auf x86. Vor dem Build, müssen Sie möglicherweise auch Ihre Lösung neu zuweisen, um mit den Visual Studio 2022-Buildtools zu entwickeln. Klicken Sie mit der rechten Maustaste auf die Lösung, wählen Sie die Lösung neu zuweisen aus und aktualisieren Sie das Plattformtoolset auf v143.

  7. Erstellen und Ausführen der App, um das benutzerdefinierte NameReporter-Steuerelement anzuzeigen.

Bekannte Probleme

  • Die Verwendung einer C#-Komponente als Projektreferenz muss PublishReadyToRun auf False festgelegen. Weitere Details finden Sie unter Github Issue #1151.
  • Die Verwendung einer für AnyCPU von C++ erstellten C#-Komponente wird derzeit nur von x86-Anwendungen unterstützt. x64 und Arm64 Apps führen zu einem Laufzeitfehler ähnlich: %1 ist keine gültige Win32-Anwendung. Weitere Details finden Sie unter Github Issue #1151 .