Compartir a través de


Tutorial: Creación de un componente de C# con controles WinUI 3 y consumo desde una aplicación C++/WinRT del SDK para aplicaciones de Windows

C#/WinRT proporciona soporte para 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 SDK para aplicaciones de Windows. Se recomienda usar C#/WinRT v1.6.4 o posterior para crear componentes en tiempo de ejecución con soporte del empaquetado de NuGet.

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

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

Prerequisites

En este tutorial se requieren los siguientes componentes y herramientas:

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

  1. Cree un nuevo proyecto de biblioteca de C# con la plantilla Biblioteca de clases (WinUI 3 en escritorio) proporcionada por el SDK para aplicaciones de Windows. En este tutorial hemos denominado el proyecto de biblioteca WinUIComponentCs, y la solución AuthoringWinUI.

    Deje desactivada la casilla Situar solución y proyecto en el mismo directorio (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#).

    Cuadro de diálogo Nueva biblioteca

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

  3. Instale la versión más reciente del paquete NuGet Microsoft.Windows.CsWinRT en el proyecto.

    i. En el Explorador de soluciones, haga clic con el botón derecho en el nodo del proyecto y seleccione Administrar paquetes NuGet.

    ii. Busque el paquete NuGet Microsoft.Windows.CsWinRT e instale la última versión.

  4. Agregue las siguientes propiedades al proyecto de biblioteca:

    <PropertyGroup>   
        <CsWinRTComponent>true</CsWinRTComponent>
    </PropertyGroup>
    
    • La propiedad CsWinRTComponent especifica que el proyecto es un componente de Windows Runtime, por lo que se genera un archivo .winmd cuando compila el componente.
  5. Agregue un control personalizado o un control de usuario a la biblioteca. Para ello, haga clic con el botón derecho en el proyecto en Visual Studio, haga clic en Agregar>Nuevo elemento y seleccione WinUI en el panel izquierdo. Para este tutorial hemos agregado un nuevo Control de usuario (WinUI 3) y se le ha asignado el nombre NameReporter.xaml. El control de usuario NameReporter permite a un usuario introducir 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 archivo NameReporter.xaml:

    <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 proyecto WinUIComponentCs para generar un archivo .winmd para el componente.

Nota

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

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

En los pasos siguientes se muestra cómo consumir el componente creado a partir de la sección anterior desde una aplicación C++/WinRT de SDK para aplicaciones de Windows. El consumo de un componente de C#/WinRT desde C++ actualmente requiere usar la plantilla Aplicación vacía, empaquetada (WinUI 3 en escritorio) de un solo proyecto. 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 empaquetado de aplicaciones de Windows (WAP) independiente. Consulte Creación de componentes de C#/WinRT en el repositorio de GitHub de C#/WinRT para obtener las actualizaciones más recientes en las configuraciones de proyecto admitidas.

  1. Agregue un nuevo proyecto de aplicación de C++ SDK de Aplicaciones para Windows a la solución. Haga clic con el botón derecho en la solución en Visual Studio y seleccione Agregar>Nuevo proyecto. Seleccione la plantilla Aplicación en blanco, Empaquetada (WinUI 3 en escritorio) de C++ proporcionada por el SDK para aplicaciones de Windows. En este tutorial hemos llamado a la aplicación CppApp.

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

    Nota

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

  3. En el archivo de encabezado pch.h de 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 una incidencia conocida por la que el archivo Package.appxmanifest no aparece en el Explorador de soluciones de Visual Studio. Para evitarlo, haga clic con el botón derecho en el proyecto de C++, seleccione Descargar proyecto y haga doble clic en el proyecto para abrir el archivo CppApp.vcxproj. Agregue la siguiente entrada al archivo del proyecto y, a continuación, vuelva a cargar el proyecto:

    <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 ActivatableClass adicional para la clase WinUIComponentCs.WinUIComponentCs_XamlTypeInfo.XamlMetaDataProvider para activar los tipos WinUI. Haga clic con el botón derecho en el archivo Package.appxmanifest 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 redestinar 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 Redestinar solución y actualice el conjunto de herramientas de plataforma a v143.

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

Problemas conocidos

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