Compartir por


Tutorial: Crear un componente de C# con controles WinUI 3 y consumirlo desde una aplicación de C++/WinRT que usa el Windows App SDK

C#/WinRT proporciona compatibilidad con la creación de componentes de Windows Runtime, incluidos los tipos personalizados de WinUI y los controles personalizados. Estos componentes se pueden consumir desde aplicaciones de C# o C++/WinRT que usan el Windows App SDK. Se recomienda usar C#/WinRT v1.6.4 o posterior para crear componentes en tiempo de ejecución con compatibilidad con el empaquetado de NuGet.

Para obtener más información sobre los escenarios admitidos, consulte Authoring C#/WinRT components en el repositorio de GitHub de C#/WinRT.

En este tutorial se muestra cómo crear un componente de C# con un control WinUI personalizado y cómo consumir ese componente desde una aplicación de C++/WinRT mediante las plantillas de Windows App SDK project.

Prerrequisitos

Este tutorial requiere las siguientes herramientas y componentes:

Creación del componente de C#/WinRT mediante el Windows App SDK

  1. Cree un nuevo proyecto de biblioteca de C# utilizando la plantilla Class Library (WinUI in Desktop) proporcionada por el Windows App SDK. Para esta guía, hemos denominado la biblioteca del proyecto WinUIComponentCs y la solución AuthoringWinUI.

    Deje la casilla Ubicar solución y proyecto en el mismo directorio sin marcar (de lo contrario, la carpeta packages para la aplicación de C++ en la sección anterior terminará interfiriendo con el proyecto de biblioteca de C#).

    Nueva biblioteca cuadro de diálogo

  2. Elimine el Class1.cs archivo que se incluye de forma predeterminada.

  3. Instalar el paquete NuGet Microsoft.Windows.CsWinRT en tu proyecto.

    i. En Solution Explorer, haga clic con el botón derecho en el nodo project y seleccione Administrar paquetes NuGet.

    ii. Busque el paquete NuGet Microsoft.Windows.CsWinRT e instale la versión más reciente.

  4. Agregue las siguientes propiedades a su proyecto de biblioteca:

    <PropertyGroup>   
        <CsWinRTComponent>true</CsWinRTComponent>
    </PropertyGroup>
    
    • La propiedad CsWinRTComponent especifica que el proyecto es un componente de Windows Runtime para que se genere un archivo .winmd al compilar el proyecto.
  5. Agregue un control personalizado o un control de usuario a la biblioteca. Para hacer esto, haga clic con el botón derecho en su proyecto en Visual Studio, haga clic en Agregar>Nuevo elemento y seleccione WinUI en el panel izquierdo. En este tutorial, agregamos un nuevo control de usuario (WinUI) y le dimos el nombre NameReporter.xaml. El control de usuario NameReporter permite a un usuario escribir un nombre y apellido en el control TextBox adecuado y hacer clic en un botón. A continuación, el control muestra un cuadro de mensaje con el nombre especificado por el usuario.

  6. Pegue el código siguiente en el NameReporter.xaml archivo:

    <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. Agregue el método siguiente a 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();
    }
    
  8. Ahora puede compilar el WinUIComponentCs proyecto para generar un .winmd para el componente.

Nota:

También puede empaquetar el componente como un paquete NuGet para que los consumidores finales de la aplicación hagan referencia. Para obtener más información, consulte Authoring C#/WinRT components en el repositorio de Github de C#/WinRT.

Hacer referencia al componente desde una aplicación de C++/WinRT de Windows App SDK

En los pasos siguientes se muestra cómo consumir el componente creado a partir de la sección anterior de una aplicación de Windows App SDK de C++/WinRT. El consumo de un componente de C#/WinRT desde C++ actualmente requiere usar la plantilla de proyecto único Blank App, Empaquetada (WinUI en escritorio). Tenga en cuenta que también se puede hacer referencia a los componentes de C# desde aplicaciones empaquetadas de C# sin registros de clases.

Actualmente no se admite el consumo de aplicaciones empaquetadas que usan un proyecto de Windows Application Packaging (WAP). Consulte Authoring C#/WinRT components en el repositorio de GitHub de C#/WinRT para las últimas actualizaciones sobre las configuraciones de proyecto soportadas.

  1. Agregue un nuevo proyecto de aplicación de Windows App SDK de C++ a su solución. Haga clic con el botón derecho en la solución en Visual Studio y seleccione Agregar>Nuevo Project. Seleccione la plantilla C++ Blank App, Empaquetada (WinUI en escritorio) proporcionada por el Windows App SDK. En este tutorial, llamamos a la aplicación CppApp.

  2. Agregue una referencia de proyecto de la aplicación de C++ al componente de C#. En Visual Studio, haga clic con el botón derecho en el project de C++ y elija Agregar>Reference y seleccione el WinUIComponentCs project.

    Nota:

    El consumo de componentes como referencia de paquete NuGet se admite con algunas limitaciones. Es decir, los componentes con controles de usuario personalizados no se pueden consumir actualmente como referencia de paquete NuGet.

  3. En el archivo de encabezado de pch.h la aplicación, agregue las siguientes líneas:

    #include <winrt/WinUIComponentCs.h>
    #include <winrt/WinUIComponentCs.WinUIComponentCs_XamlTypeInfo.h>
    
  4. Abra el archivo de manifiesto del paquete Package.appxmanifest.

    Nota:

    Hay un problema conocido por el que el archivo Package.appxmanifest no aparece en Visual Studio Solution Explorer. Para solucionarlo, haga clic con el botón derecho en el project de C++, seleccione Unload Project y haga doble clic en el project para abrir el archivo CppApp.vcxproj. Agregue la entrada siguiente al archivo project y, a continuación, vuelva a cargar el project:

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

    En Package.appxmanifest, agregue los siguientes registros de clases activables. También necesitarás una entrada adicional de ActivatableClass para la clase WinUIComponentCs.WinUIComponentCs_XamlTypeInfo.XamlMetaDataProvider con el fin de activar los tipos de WinUI. Haga clic con el botón derecho en el Package.appxmanifest archivo y seleccione Abrir con>XML (Editor de texto) para editar el archivo.

    <!--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. Abra el archivo MainWindow.xaml.

    i. Agregue una referencia al espacio de nombres del componente en la parte superior del archivo.

    xmlns:custom="using:WinUIComponentCs"
    

    ii. Agregue el control de usuario al código XAML existente.

    <StackPanel>
        ...
        <custom:NameReporter/>
    </StackPanel>
    
  6. Establezca CppApp como proyecto de inicio, haga clic con el botón derecho en CppApp y seleccione Establecer como Proyecto de Inicio. Establezca la configuración de la solución en x86. Antes de compilar, es posible que también tenga que volver a configurar la solución para compilar con las herramientas de compilación de Visual Studio 2022. Haga clic con el botón derecho en la solución, seleccione Retarget de la solución y actualice el conjunto de herramientas de plataforma a v143.

  7. Compile y ejecute la aplicación para ver el control personalizado NameReporter.

Problemas conocidos

  • El consumo de un componente de C# como referencia de proyecto requiere que PublishReadyToRun se establezca en False. Consulte Github problema n.º 1151 para obtener más información.
  • El consumo de un componente de C# creado para AnyCPU desde C++ solo se admite actualmente desde x86 aplicaciones. x64 y Arm64 aplicaciones dan como resultado un error en tiempo de ejecución similar al siguiente: %1 no es una aplicación Win32 válida. Vea Github Problema #1151 para obtener más detalles.