チュートリアル — WinUI 3 コントロールを使用して C# コンポーネントを作成し、Windows App SDK を使用する C++/WinRT アプリから使用する

C#/WinRT では、WinUI のカスタム型やカスタム コントロールなど、Windows ランタイム コンポーネントの作成がサポートされています。 これらのコンポーネントは、Windows App SDKを使う C# または C++/WinRT アプリケーションから使用できます。 C#/WinRT v1.6.4 以降を使って、NuGet のパッケージ化をサポートするランタイム コンポーネントを作成することをお勧めします。

サポートされるシナリオについて詳しくは、C#/WinRT GitHub リポジトリの「C#/WinRT コンポーネントの作成」をご覧ください。

このチュートリアルでは、カスタム WinUI 3 コントロールを使って C# コンポーネントを作成する方法と、Windows App SDK プロジェクト テンプレートを使って C++/WinRT アプリからそのコンポーネントを利用する方法を示します。

前提条件

このチュートリアルでは、次のツールとコンポーネントが必要です。

Windows App SDK を使用して C#/WinRT コンポーネントを作成する

  1. Windows App SDK によって提供されるクラス ライブラリ (デスクトップでは WinUI 3) テンプレートを使って、新しい C# ライブラリ プロジェクトを作成します。 このチュートリアルでは、ライブラリ プロジェクトの名前を WinUIComponentCs、ソリューションの名前を AuthoringWinUI にします。

    [ソリューションとプロジェクトを同じディレクトリに配置する] ボックスはオフのままにします (そうしないと、前のセクションの C++ アプリケーション用の packages フォルダーが、C# ライブラリ プロジェクトと干渉するようになります)。

    [新しいライブラリ] ダイアログ

  2. 既定で含まれる Class1.cs ファイルを削除します。

  3. 最新の Microsoft.Windows.CsWinRT NuGet パッケージをプロジェクトにインストールします。

    i. ソリューション エクスプローラーでプロジェクト ノードを右クリックして、[NuGet パッケージの管理] を選びます。

    ii. Microsoft.Windows.CsWinRT NuGet パッケージを検索し、最新バージョンをインストールします。

  4. 次のプロパティをライブラリ プロジェクトに追加します。

    <PropertyGroup>   
        <CsWinRTComponent>true</CsWinRTComponent>
    </PropertyGroup>
    
    • CsWinRTComponent プロパティは、プロジェクトが Windows ランタイム コンポーネントであることを指定します。これにより、プロジェクトをビルドすると .winmd ファイルが生成されます。
  5. カスタム コントロールまたはユーザー コントロールをライブラリに追加します。 これを行うには、Visual Studio でプロジェクトを右クリックし、[追加]>[新しい項目] をクリックして、左のペインで [WinUI] を選びます。 このチュートリアルでは、新しいユーザー コントロール (WinUI 3) を追加し、それに NameReporter.xaml という名前を付けます。 NameReporter ユーザー コントロールを使うと、ユーザーは適切な TextBox コントロールに姓と名を入力して、ボタンをクリックできます。 その後、ユーザーが入力した名前を含むメッセージ ボックスがコントロールに表示されます。

  6. 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. 次のメソッドを 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. これで、WinUIComponentCs プロジェクトをビルドして、コンポーネント用の .winmd ファイルを生成できるようになります。

注意

また、エンド アプリ コンシューマーが参照できるよう、NuGet パッケージとしてコンポーネントをパッケージ化することもできます。 詳しくは、C#/WinRT Github リポジトリの「C#/WinRT コンポーネントの作成」をご覧ください。

Windows App SDK C++/WinRT アプリからコンポーネントを参照する

次の手順では、C++/WinRT Windows App SDK アプリケーションから前のセクションで作成したコンポーネントを利用する方法を示します。 C++ から C#/WinRT コンポーネントを使うには、現在、単一プロジェクトの Blank App, Packaged (WinUI 3 in Desktop) (空のアプリ、パッケージ (デスクトップの WinUI 3)) テンプレートを使う必要があります。 C# コンポーネントは、クラスの登録なしで C# パッケージ アプリから参照することもできます。

別の Windows アプリケーション パッケージ (WAP) プロジェクトを使うパッケージ アプリからの使用は、現在サポートされていません。 サポートされるプロジェクト構成の最新の更新については、C#/WinRT GitHub リポジトリの「C#/WinRT コンポーネントの作成」をご覧ください。

  1. 新しい C++ Windows App SDK アプリケーション プロジェクトをソリューションに追加します。 Visual Studio でソリューションを右クリックし、[追加]>[新しいプロジェクト] を選びます。 Windows App SDKによって提供される Blank App, Packaged (WinUI 3 in Desktop) (空のアプリ、パッケージ (デスクトップの WinUI 3)) テンプレートを選びます。 このチュートリアルでは、アプリに CppApp という名前を付けました。

  2. C++ アプリから C# コンポーネントへのプロジェクト参照を追加します。 Visual Studio で C++ プロジェクトを右クリックし、[追加]>[参照] を選んで、WinUIComponentCs プロジェクトを選びます。

    注意

    NuGet パッケージ参照としてのコンポーネントの使用は、いくつかの制限付きでサポートされています。 つまり、カスタム ユーザー コントロールを含むコンポーネントは、現在、NuGet パッケージ参照として使用できません。

  3. アプリの pch.h ヘッダー ファイルに、次の行を追加します。

    #include <winrt/WinUIComponentCs.h>
    #include <winrt/WinUIComponentCs.WinUIComponentCs_XamlTypeInfo.h>
    
  4. パッケージ マニフェスト ファイル Package.appxmanifest を開きます。

    注意

    Package.appxmanifest ファイルが Visual Studio のソリューション エクスプローラーに表示されないという既知の問題があります。 これを回避するには、C++ プロジェクトを右クリックして、[プロジェクトのアンロード] を選び、プロジェクトをダブルクリックして CppApp.vcxproj ファイルを開きます。 プロジェクト ファイルに次のエントリを追加してから、プロジェクトをもう一度読み込みます。

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

    Package.appxmanifest で、次のアクティブ化可能なクラス登録を追加します。 WinUI の型をアクティブにするには、WinUIComponentCs.WinUIComponentCs_XamlTypeInfo.XamlMetaDataProvider クラスの追加の ActivatableClass エントリも必要です。 ファイルを編集するには、Package.appxmanifest ファイルを右クリックして、[プログラムから開く]>[XML (テキスト エディター)] を選びます。

    <!--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. MainWindow.xaml ファイルを開きます。

    i. ファイルの先頭に、コンポーネントの名前空間への参照を追加します。

    xmlns:custom="using:WinUIComponentCs"
    

    ii. 既存の XAML コードにユーザー コントロールを追加します。

    <StackPanel>
        ...
        <custom:NameReporter/>
    </StackPanel>
    
  6. CppApp をスタートアップ プロジェクトとして設定します。CppApp を右クリックして、[スタートアップ プロジェクトとして設定] を選びます。 ソリューションの構成を x86 に設定します。 ビルドする前に、Visual Studio 2022 ビルド ツールでビルドするため、ソリューションのターゲット変更が必要になる場合もあります。 ソリューションを右クリックし、[ソリューションの再ターゲット] を選んで、プラットフォーム ツールセットを v143 にアップグレードします。

  7. アプリをビルドして実行して、カスタム NameReporter コントロールを表示します。

既知の問題

  • C# コンポーネントをプロジェクト参照として使うには、PublishReadyToRunFalse に設定する必要があります。 詳しくは、Github イシュー #1151 をご覧ください。
  • AnyCPU 用にビルドされた C# コンポーネントの C++ からの使用は、現在、x86 アプリケーションからのみサポートされています。 x64 および Arm64 アプリでは、次のようなランタイム エラーが発生します: "%1 は有効な Win32 アプリケーションではありません"。詳しくは、Github イシュー #1151 をご覧ください。