C# を使用して XAML コントロールを作成する

この記事では、C# で WinUI 3 のテンプレート化された XAML コントロールを作成する手順について説明します。 テンプレート化されたコントロールは Microsoft.UI.Xaml.Controls.Control から継承され、XAML コントロール テンプレートを使用してカスタマイズできる視覚的な構造と視覚的な動作を持っています。

C# と C++/WinRT アプリの両方から使用するために、C# でスタンドアロン WinUI 3 コンポーネントを作成するには、「チュートリアル: WinUI 3 コントロールを使用して C# コンポーネントを作成し、C++ Windows App SDK アプリケーションから使用する」を参照してください。

前提条件

  1. 開発環境のセットアップ — 「Windows App SDK 用のツールをインストールする」を参照してください。
  2. 最初の WinUI 3 プロジェクトを作成する」の指示に従います。

空のアプリを作成する (BgLabelControlApp)

まず、Microsoft Visual Studio で、新しいプロジェクトを作成します。 [新しいプロジェクトの作成] ダイアログで、[空のアプリ、パッケージ (WinUI 3 in Desktop)] プロジェクト テンプレートを選択します。このとき、必ず C# 言語バージョンを選択します。 プロジェクト名を "BgLabelControlApp" に設定して、ファイル名が次の例のコードと一致するようにします。

Blank App Project Template

テンプレート コントロールをアプリに追加する

テンプレート コントロールを追加するには、ツール バーの [プロジェクト] メニューをクリックするか、ソリューション エクスプローラーでプロジェクトを右クリックし、[新しい項目の追加] を選択します。 [Visual C#] -> [WinUI] の下で、[カスタム コントロール (WinUI 3)] テンプレートを選択します。 新しいコントロールに "BgLabelControl" という名前を指定し、[追加] をクリックします。

カスタム コントロール C# ファイルを更新する

C# ファイルの BgLabelControl.cs では、コンストラクターによってコントロールの DefaultStyleKey プロパティが定義されていることに注意してください。 このキーでは、コントロールのコンシューマーがテンプレートを明示的に指定していない場合に使用される既定のテンプレートを識別します。 今作成しているコントロールの場合、キーの値は "type" です。 このキーは、後で汎用テンプレート ファイルを実装するときに使用します。

public BgLabelControl()
{
    this.DefaultStyleKey = typeof(BgLabelControl);
}

今作成しているテンプレート コントロールには、コード内か XAML 内で、またはデータ バインディングを使用してプログラムから設定できるテキスト ラベルがあります。 システムでコントロールのラベルのテキストを最新の状態に保つためには、それを DependencyPropety として実装する必要があります。 これを行うには、まず文字列プロパティを宣言して Label という名前を付けます。 バッキング変数を使用する代わりに、GetValueSetValue を呼び出すことによって依存関係プロパティの値の設定と取得を行います。 これらのメソッドは、Microsoft.UI.Xaml.Controls.Control が継承する DependencyObject によって提供されます。

public string Label
{
    get => (string)GetValue(LabelProperty);
    set => SetValue(LabelProperty, value);
}

次に、依存関係プロパティを宣言し、それをシステムに登録するために、DependencyProperty.Register を呼び出します。 このメソッドでは、Label プロパティの名前と型、プロパティの所有者の型 (BgLabelControl クラス)、およびプロパティの既定値を指定します。

DependencyProperty LabelProperty = DependencyProperty.Register(
    nameof(Label), 
    typeof(string),
    typeof(BgLabelControl), 
    new PropertyMetadata(default(string), new PropertyChangedCallback(OnLabelChanged)));

依存関係プロパティを実装するために必要な手順はこの 2 つだけですが、この例では、OnLabelChanged イベントに対する省略可能なハンドラーを追加します。 このイベントは、プロパティ値が更新されるたびにシステムによって発生させられます。 この例では、新しいラベルのテキストが空の文字列であるかどうかを確認し、それに応じてクラス変数を更新します。

public bool HasLabelValue { get; set; }

private static void OnLabelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    BgLabelControl labelControl = d as BgLabelControl; //null checks omitted
    String s = e.NewValue as String; //null checks omitted
    if (s == String.Empty)
    {
        labelControl.HasLabelValue = false;
    }
    else
    {
        labelControl.HasLabelValue = true;
    }
}

依存関係プロパティのしくみについて詳しくは、「依存関係プロパティの概要」をご覧ください。

BgLabelControl の既定のスタイルを定義する

テンプレート コントロールでは、コントロールのユーザーが明示的にスタイルを設定しない場合に使用される既定のスタイル テンプレートを提供する必要があります。 このステップでは、コントロールの汎用テンプレート ファイルに変更を加えます。

汎用テンプレート ファイルは、カスタム コントロール (WinUI) をアプリに追加するときに生成されます。 ファイルの名前は "Generic.xaml" で、ソリューション エクスプローラーの [テーマ] フォルダー内に生成されます。 XAML フレームワークでテンプレート コントロールの既定のスタイルを検出するために、フォルダーとファイルの名前が必要です。 Generic.xaml の既定のコンテンツを削除し、以下のマークアップを貼り付けます。

<!-- \Themes\Generic.xaml -->
<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:BgLabelControlApp">

    <Style TargetType="local:BgLabelControl" >
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="local:BgLabelControl">
                    <Grid Width="100" Height="100" Background="{TemplateBinding Background}">
                        <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="{TemplateBinding Label}"/>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

この例では、Style 要素の TargetType 属性が BgLabelControlApp 名前空間内の BgLabelControl 型に設定されていることがわかります。 この型は、上記のコントロールのコンストラクターで DefaultStyleKey プロパティに対して指定したものと同じ値です。これにより、これがコントロールの既定のスタイルとして指定されます。

コントロール テンプレート内の TextBlockText プロパティは、このコントロールの Label 依存関係プロパティにバインドされています。 このプロパティにバインドするには、TemplateBinding マークアップ拡張機能を使用します。 また、この例では、Grid の背景を、Control クラスから継承されている Background 依存関係プロパティにバインドしています。

メイン UI ページに BgLabelControl のインスタンスを追加する

MainWindow.xaml を開くと、メイン UI ページの XAML マークアップが含まれています。 Button 要素の直後 (StackPanel 内) に次のマークアップを追加します。

<local:BgLabelControl Background="Red" Label="Hello, World!"/>

アプリをビルドして実行すると、指定した背景色とラベルを持つテンプレート コントロールが表示されます。

Templated control result

関連項目