チュートリアル: Windows フォームでの WPF 複合コントロールのホスト

Windows Presentation Foundation (WPF) は、アプリケーションの作成に適した環境を提供します。 ただし、Windows フォームのコードに多大な手間と時間をかけた場合は、それを最初から書き直すよりも、既存の Windows フォーム アプリケーションを WPF で拡張する方が効率的な場合もあります。 一般的なシナリオとして、Windows フォーム アプリケーションに、WPF を使用して実装したコントロールを埋め込む場合が挙げられます。 WPF コントロールのカスタマイズの詳細については、「コントロールのカスタマイズ」を参照してください。

このチュートリアルでは、Windows フォーム アプリケーション内で WPF 複合コントロールをホストしてデータ エントリを実行するアプリケーションについて、順を追って説明します。 複合コントロールは DLL にパッケージ化されています。 この一般的な手順は、より複雑なアプリケーションやコントロールに拡張することができます。 このチュートリアルは、外観および機能が「チュートリアル: WPF での Windows フォーム複合コントロールのホスト」とほぼ同じ構成になっています。 主な違いは、ホストする側とされる側が逆であることです。

このチュートリアルは、2 つのセクションに分かれています。 最初のセクションでは、WPF 複合コントロールの実装について簡単に説明します。 2 番目のセクションでは、Windows フォーム アプリケーションで複合コントロールをホストし、コントロールからイベントを受け取って、コントロールのプロパティの一部にアクセスする方法について詳しく説明します。

このチュートリアルでは、以下のタスクを行います。

  • WPF 複合コントロールを実装する。

  • Windows フォーム ホスト アプリケーションを実装する。

このチュートリアルで示すタスクの完全なコード一覧については、Windows フォームでの WPF 複合コントロールのホストのサンプルに関するページを参照してください。

必須コンポーネント

このチュートリアルを完了するには Visual Studio が必要です。

WPF 複合コントロールの実装

この例で使用される WPF 複合コントロールは、ユーザーの名前とアドレスを受け取る単純なデータ入力フォームです。 ユーザーが 2 つのボタンのいずれかをクリックして入力操作が終了したことを示すと、コントロールはカスタム イベントを発生させて入力情報をホストに返します。 次の図はレンダリングされたコントロールを示しています。

次の図は WPF 複合コントロールを示したものです。

シンプルな WPF コントロールを示すスクリーンショット。

プロジェクトの作成

プロジェクトを開始するには

  1. Visual Studio を起動し、 [新しいプロジェクト] ダイアログ ボックスを開きます。

  2. Visual C# および Windows のカテゴリで、 [WPF ユーザー コントロール ライブラリ] テンプレートを選択します。

  3. 新しいプロジェクトに MyControls という名前を付けます。

  4. 配置場所として、WindowsFormsHostingWpfControl など、わかりやすい名前を付けた最上位フォルダーを指定します。 このフォルダーには後でホスト アプリケーションも配置します。

  5. [OK] をクリックして、プロジェクトを作成します。 既定のプロジェクトには、UserControl1 という名前の 1 つのコントロールが含まれます。

  6. ソリューション エクスプローラーで、UserControl1MyControl1 という名前に変更します。

プロジェクトは、以下のシステム DLL を参照している必要があります。 これらの DLL のいずれかが既定で含まれていない場合は、プロジェクトに追加します。

  • PresentationCore

  • PresentationFramework

  • システム

  • WindowsBase

ユーザー インターフェイスの作成

複合コントロールのユーザー インターフェイス (UI) は、Extensible Application Markup Language (XAML) を使用して実装されます。 複合コントロールの UI は、5 つの TextBox 要素で構成されています。 各 TextBox 要素には、ラベルとして使用される TextBlock 要素が関連付けられています。 さらに下部には [OK][Cancel] という 2 つの Button 要素があります。 ユーザーがいずれかのボタンをクリックすると、コントロールは情報をホストに返すカスタム イベントを発生させます。

基本的なレイアウト

Grid 要素には、さまざまな UI 要素が格納されます。 Grid を使用して、HTML で Table 要素を使用する場合とほぼ同じ方法で、複合コントロールのコンテンツを配置できます。 WPF には Table 要素もありますが、Grid の方が軽量で、単純なレイアウト タスクに適しています。

次の XAML に基本的なレイアウトを示します。 この XAML では、Grid 要素に列および行の数を指定することにより、コントロールの全体的な構造が定義されています。

MyControl1.xaml で、で、既存の XAML を次の XAML で置き換えます。

<Grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      x:Class="MyControls.MyControl1"
      Background="#DCDCDC"
      Width="375"
      Height="250"
      Name="rootElement"
      Loaded="Init">

  <Grid.ColumnDefinitions>
    <ColumnDefinition Width="Auto" />
    <ColumnDefinition Width="Auto" />
    <ColumnDefinition Width="Auto"/>
    <ColumnDefinition Width="Auto"/>
  </Grid.ColumnDefinitions>

  <Grid.RowDefinitions>
    <RowDefinition Height="Auto" />
    <RowDefinition Height="Auto" />
    <RowDefinition Height="Auto" />
    <RowDefinition Height="Auto" />
    <RowDefinition Height="Auto" />
    <RowDefinition Height="Auto" />
  </Grid.RowDefinitions>
</Grid>

TextBlock および TextBox 要素のグリッドへの追加

グリッドに UI 要素を配置するには、その要素の RowProperty および ColumnProperty 属性を適切な行番号と列番号に設定します。 行と列の番号付けは 0 から始まることに注意してください。 ColumnSpanProperty 属性を設定することによって、1 つの要素を複数の列にまたがって表示することができます。 Grid 要素の詳細については、「グリッド要素を作成する」を参照してください。

次の XAML では、複合コントロールの TextBox 要素と TextBlock 要素およびそれらの RowProperty 属性と ColumnProperty 属性が示されており、要素をグリッドに適切に配置するために属性が設定されています。

MyControl1.xaml で、次の XAML を Grid 要素内に追加します。

  <TextBlock Grid.Column="0"
        Grid.Row="0" 
        Grid.ColumnSpan="4"
        Margin="10,5,10,0"
        HorizontalAlignment="Center"
        Style="{StaticResource titleText}">Simple WPF Control</TextBlock>

  <TextBlock Grid.Column="0"
        Grid.Row="1"
        Style="{StaticResource inlineText}"
        Name="nameLabel">Name</TextBlock>
  <TextBox Grid.Column="1"
        Grid.Row="1"
        Grid.ColumnSpan="3"
        Name="txtName"/>

  <TextBlock Grid.Column="0"
        Grid.Row="2"
        Style="{StaticResource inlineText}"
        Name="addressLabel">Street Address</TextBlock>
  <TextBox Grid.Column="1"
        Grid.Row="2"
        Grid.ColumnSpan="3"
        Name="txtAddress"/>

  <TextBlock Grid.Column="0"
        Grid.Row="3"
        Style="{StaticResource inlineText}"
        Name="cityLabel">City</TextBlock>
  <TextBox Grid.Column="1"
        Grid.Row="3"
        Width="100"
        Name="txtCity"/>

  <TextBlock Grid.Column="2"
        Grid.Row="3"
        Style="{StaticResource inlineText}"
        Name="stateLabel">State</TextBlock>
  <TextBox Grid.Column="3"
        Grid.Row="3"
        Width="50"
        Name="txtState"/>

  <TextBlock Grid.Column="0"
        Grid.Row="4"
        Style="{StaticResource inlineText}"
        Name="zipLabel">Zip</TextBlock>
  <TextBox Grid.Column="1"
        Grid.Row="4"
        Width="100"
        Name="txtZip"/>

UI 要素のスタイル設定

データ入力フォームの多くの要素は外観が似ていますが、それは、そのいくつかのプロパティの設定が同一であることを意味しています。 前の XAML では、各要素の属性を個別に設定するのではなく、Style 要素を使用して、複数要素のクラスの標準プロパティ設定を定義しています。 この方法だと、コントロールの複雑さが軽減され、1 つのスタイル属性を使用して複数要素の外観を変更することができます。

Style 要素は Grid 要素の Resources プロパティに含まれるため、コントロール内のすべての要素で使用できます。 スタイルに名前が付いている場合は、そのスタイルの名前に設定された Style 要素を追加することによって、そのスタイルを要素に適用します。 名前が付いていないスタイルは、その要素の既定のスタイルになります。 WPF のスタイルの詳細については、「スタイルとテンプレート」を参照してください。

次の XAML では、複合コントロールの Style 要素が示されています。 スタイルがどのように要素に適用されるかについては、前の XAML を参照してください。 たとえば、最後の TextBlock 要素では inlineText スタイルが使用され、最後の TextBox 要素では既定のスタイルが使用されています。

MyControl1.xaml で、次の XAML を Grid 開始要素の直後に追加します。

<Grid.Resources>
  <Style x:Key="inlineText" TargetType="{x:Type TextBlock}">
    <Setter Property="Margin" Value="10,5,10,0"/>
    <Setter Property="FontWeight" Value="Normal"/>
    <Setter Property="FontSize" Value="12"/>
  </Style>
  <Style x:Key="titleText" TargetType="{x:Type TextBlock}">
    <Setter Property="DockPanel.Dock" Value="Top"/>
    <Setter Property="FontWeight" Value="Bold"/>
    <Setter Property="FontSize" Value="14"/>
    <Setter Property="Margin" Value="10,5,10,0"/>
  </Style>
  <Style TargetType="{x:Type Button}">
    <Setter Property="Margin" Value="10,5,10,0"/>
    <Setter Property="Width" Value="60"/>
  </Style>
  <Style TargetType="{x:Type TextBox}">
    <Setter Property="Margin" Value="10,5,10,0"/>
  </Style>
</Grid.Resources>

[OK] ボタンと [キャンセル] ボタンの追加

複合コントロール上の最後の要素は [OK][Cancel]Button 要素で、これらは Grid の最後の行の最初の 2 つの列を専有します。 これらの要素では、共通のイベント ハンドラーである ButtonClicked と、前の XAML で定義されている既定の Button スタイルが使用されています。

MyControl1.xaml で、次の XAML を最後の TextBox 要素の後に追加します。 複合コントロールの XAML 部分はこれで完成しました。

<Button Grid.Row="5"
        Grid.Column="0"
        Name="btnOK"
        Click="ButtonClicked">OK</Button>
<Button Grid.Row="5"
        Grid.Column="1"
        Name="btnCancel"
        Click="ButtonClicked">Cancel</Button>

分離コード ファイルの実装

分離コード ファイル MyControl1.xaml.cs では、次の 3 つの基本的なタスクが実装されます。

  1. ユーザーがいずれかのボタンをクリックしたときに発生するイベントを処理します。

  2. TextBox 要素からデータを取得し、それをカスタム イベント引数オブジェクトにパッケージ化します。

  3. カスタム OnButtonClick イベントを発生させて、ユーザーが操作終了したことをホストに通知し、入力データをホストに渡します。

コントロールは、外観を変更するための色とフォントの多くのプロパティも公開します。 Windows フォーム コントロールをホストするために使用される WindowsFormsHost クラスとは異なり、ElementHost クラスでは、コントロールの Background プロパティのみが公開されます。 このコード例と「チュートリアル: WPF での Windows フォーム複合コントロールのホスト」で説明されている例の類似性を保持するために、このコントロールでは残りのプロパティが直接公開されます。

分離コード ファイルの基本構造

分離コード ファイルは、MyControl1MyControlEventArgs という 2 つのクラスを格納する単一の名前空間である MyControls で構成されています。

namespace MyControls  
{  
  public partial class MyControl1 : Grid  
  {  
    //...  
  }  
  public class MyControlEventArgs : EventArgs  
  {  
    //...  
  }  
}  

最初のクラスである MyControl1 は、MyControl1.xaml で定義された UI 機能を実装するコードを格納する部分クラスです。 MyControl1.xaml が解析されると、XAML は同じ部分クラスに変換され、2 つの部分クラスがマージされて、コンパイルされたコントロールを形成します。 このため、分離コード ファイル内のクラス名は MyControl1.xaml に割り当てられたクラス名と一致する必要があり、コントロールのルート要素から継承する必要があります。 2 番目のクラスである MyControlEventArgs はホストにデータを返送するために使用されるイベント引数クラスです。

MyControl1.xaml.cs を開きます。 既存のクラス宣言を以下の名前に合わせて変更し、Grid を継承するようにします。

public partial class MyControl1 : Grid

コントロールの初期化

このコードでは、次の基本タスクを実装します。

  • プライベート イベント OnButtonClick と、それに関連付けられたデリゲート MyControlEventHandler を宣言します。

  • ユーザーのデータを格納するいくつかのプライベート グローバル変数を作成します。 このデータは、対応するプロパティを通じて公開されます。

  • コントロールの Loaded イベントのハンドラー Init を実装します。 このハンドラーは、MyControl1.xaml で定義された値をグローバル変数に割り当てることで、グローバル変数を初期化します。 これを行うには、標準的な TextBlock 要素である nameLabel に割り当てられた Name を使用して、その要素のプロパティ設定にアクセスします。

既存のコンストラクターを削除し、次のコードを MyControl1 クラスに追加します。

public delegate void MyControlEventHandler(object sender, MyControlEventArgs args);
public event MyControlEventHandler OnButtonClick;
private FontWeight _fontWeight;
private double _fontSize;
private FontFamily _fontFamily;
private FontStyle _fontStyle;
private SolidColorBrush _foreground;
private SolidColorBrush _background;

private void Init(object sender, EventArgs e)
{
    //They all have the same style, so use nameLabel to set initial values.
    _fontWeight = nameLabel.FontWeight;
    _fontSize = nameLabel.FontSize;
    _fontFamily = nameLabel.FontFamily;
    _fontStyle = nameLabel.FontStyle;
    _foreground = (SolidColorBrush)nameLabel.Foreground;
    _background = (SolidColorBrush)rootElement.Background;
}

ボタンのクリック イベントの処理

ユーザーは [OK] ボタンまたは [Cancel] ボタンをクリックすることによって、データ入力タスクが完了したことを示します。 どちらのボタンでも、同じ Click イベント ハンドラーである ButtonClicked が使用されています。 これらのボタンにはそれぞれ btnOK または btnCancel という名前が付けられているので、ハンドラーでは sender 引数の値を調べることによって、どちらのボタンがクリックされたかを判断することができます。 ハンドラーは次の処理を行います。

  • TextBox 要素からのデータを格納する MyControlEventArgs オブジェクトを作成します。

  • ユーザーが [Cancel] ボタンをクリックした場合は、MyControlEventArgs オブジェクトの IsOK プロパティを false に設定します。

  • ユーザーが操作を終了したことをホストに示す OnButtonClick イベントを発生させ、収集したデータを渡します。

次のコードを、MyControl1 クラスの Init メソッドの後に追加します。

private void ButtonClicked(object sender, RoutedEventArgs e)
{
    MyControlEventArgs retvals = new MyControlEventArgs(true,
                                                        txtName.Text,
                                                        txtAddress.Text,
                                                        txtCity.Text,
                                                        txtState.Text,
                                                        txtZip.Text);
    if (sender == btnCancel)
    {
        retvals.IsOK = false;
    }
    if (OnButtonClick != null)
        OnButtonClick(this, retvals);
}

プロパティの作成

クラスの残りの部分では単に、前に説明したグローバル変数に対応するプロパティを公開します。 プロパティが変更されると、set アクセサーは、対応する要素のプロパティを変更し、基になるグローバル変数を更新することによって、コントロールの外観を変更します。

MyControl1 クラスに次のコードを追加します。

public FontWeight MyControl_FontWeight
{
    get { return _fontWeight; }
    set
    {
        _fontWeight = value;
        nameLabel.FontWeight = value;
        addressLabel.FontWeight = value;
        cityLabel.FontWeight = value;
        stateLabel.FontWeight = value;
        zipLabel.FontWeight = value;
    }
}
public double MyControl_FontSize
{
    get { return _fontSize; }
    set
    {
        _fontSize = value;
        nameLabel.FontSize = value;
        addressLabel.FontSize = value;
        cityLabel.FontSize = value;
        stateLabel.FontSize = value;
        zipLabel.FontSize = value;
    }
}
public FontStyle MyControl_FontStyle
{
    get { return _fontStyle; }
    set
    {
        _fontStyle = value;
        nameLabel.FontStyle = value;
        addressLabel.FontStyle = value;
        cityLabel.FontStyle = value;
        stateLabel.FontStyle = value;
        zipLabel.FontStyle = value;
    }
}
public FontFamily MyControl_FontFamily
{
    get { return _fontFamily; }
    set
    {
        _fontFamily = value;
        nameLabel.FontFamily = value;
        addressLabel.FontFamily = value;
        cityLabel.FontFamily = value;
        stateLabel.FontFamily = value;
        zipLabel.FontFamily = value;
    }
}

public SolidColorBrush MyControl_Background
{
    get { return _background; }
    set
    {
        _background = value;
        rootElement.Background = value;
    }
}
public SolidColorBrush MyControl_Foreground
{
    get { return _foreground; }
    set
    {
        _foreground = value;
        nameLabel.Foreground = value;
        addressLabel.Foreground = value;
        cityLabel.Foreground = value;
        stateLabel.Foreground = value;
        zipLabel.Foreground = value;
    }
}

ホストへのデータの返送

ファイルの最後のコンポーネントは、収集されたデータをホストに返送するために使用される MyControlEventArgs クラスです。

MyControls 名前空間に次のコードを追加します。 この実装は簡単なので、これ以上の説明はしません。

public class MyControlEventArgs : EventArgs
{
    private string _Name;
    private string _StreetAddress;
    private string _City;
    private string _State;
    private string _Zip;
    private bool _IsOK;

    public MyControlEventArgs(bool result,
                              string name,
                              string address,
                              string city,
                              string state,
                              string zip)
    {
        _IsOK = result;
        _Name = name;
        _StreetAddress = address;
        _City = city;
        _State = state;
        _Zip = zip;
    }

    public string MyName
    {
        get { return _Name; }
        set { _Name = value; }
    }
    public string MyStreetAddress
    {
        get { return _StreetAddress; }
        set { _StreetAddress = value; }
    }
    public string MyCity
    {
        get { return _City; }
        set { _City = value; }
    }
    public string MyState
    {
        get { return _State; }
        set { _State = value; }
    }
    public string MyZip
    {
        get { return _Zip; }
        set { _Zip = value; }
    }
    public bool IsOK
    {
        get { return _IsOK; }
        set { _IsOK = value; }
    }
}

ソリューションをビルドします。 ビルドでは、MyControls.dll という名前の DLL が生成されます。

Windows フォーム ホスト アプリケーションの実装

Windows フォーム ホスト アプリケーションでは、ElementHost オブジェクトを使用して WPF 複合コントロールがホストされます。 アプリケーションでは OnButtonClick イベントを処理して、複合コントロールからデータを受け取ります。 アプリケーションにはオプションのボタンのセットもあり、それを使用してコントロールの外観を変更することができます。 次の図は、アプリケーションを示しています。

次の図では、Windows フォーム アプリケーションでホストされる WPF 複合コントロールを示します

Avalon コントロールをホストする Windows フォームを示すスクリーンショット。

プロジェクトの作成

プロジェクトを開始するには

  1. Visual Studio を起動し、 [新しいプロジェクト] ダイアログ ボックスを開きます。

  2. Visual C# および Windows のカテゴリで、 [Windows フォーム アプリケーション] テンプレートを選択します。

  3. 新しいプロジェクトに WFHost という名前を付けます。

  4. 配置場所として、MyControls の配置先と同じ最上位フォルダーを指定します。

  5. [OK] をクリックして、プロジェクトを作成します。

MyControl1 および他のアセンブリを含む DLL への参照も追加する必要があります。

  1. ソリューション エクスプローラーで、プロジェクト名を右クリックし、 [参照の追加] を選択します。

  2. [参照] タブをクリックし、MyControls.dll が格納されているフォルダーに移動します。 このチュートリアルの場合は、MyControls\bin\Debug フォルダーです。

  3. MyControls.dll を選択し、 [OK] をクリックします。

  4. 次のアセンブリへの参照を追加します。

    • PresentationCore

    • PresentationFramework

    • System.Xaml

    • WindowsBase

    • WindowsFormsIntegration

アプリケーションのユーザー インターフェイスの実装

Windows フォーム アプリケーションの UI には、WPF 複合コントロールを操作するいくつかのコントロールが含まれています。

  1. Windows フォーム デザイナーで、Form1 を開きます。

  2. コントロールを配置するためにフォームを拡大します。

  3. フォームの右上隅に、WPF 複合コントロールを保持するための System.Windows.Forms.Panel コントロールを追加します。

  4. 次の System.Windows.Forms.GroupBox コントロールをフォームに追加します。

    名前 テキスト
    groupBox1 背景色
    groupBox2 前景色
    groupBox3 フォント サイズ
    groupBox4 フォント ファミリ
    groupBox5 [スタイル]
    groupBox6 フォントの太さ
    groupBox7 コントロールからのデータ
  5. 次の System.Windows.Forms.RadioButton コントロールを System.Windows.Forms.GroupBox コントロールに追加します。

    GroupBox 名前 テキスト
    groupBox1 radioBackgroundOriginal
    groupBox1 radioBackgroundLightGreen ライトグリーン
    groupBox1 radioBackgroundLightSalmon ライトサーモン
    groupBox2 radioForegroundOriginal
    groupBox2 radioForegroundRed
    groupBox2 radioForegroundYellow
    groupBox3 radioSizeOriginal
    groupBox3 radioSizeTen 10
    groupBox3 radioSizeTwelve 12
    groupBox4 radioFamilyOriginal
    groupBox4 radioFamilyTimes MS Pゴシック
    groupBox4 radioFamilyWingDings WingDings
    groupBox5 radioStyleOriginal 標準
    groupBox5 radioStyleItalic [斜体]
    groupBox6 radioWeightOriginal
    groupBox6 radioWeightBold [太字]
  6. 次の System.Windows.Forms.Label コントロールを最後の System.Windows.Forms.GroupBox に追加します。 これらのコントロールでは、WPF 複合コントロールから返されたデータが表示されます。

    GroupBox 名前 テキスト
    groupBox7 lblName 名前:
    groupBox7 lblAddress 番地:
    groupBox7 lblCity 市区町村:
    groupBox7 lblState 都道府県:
    groupBox7 lblZip 郵便番号:

フォームの初期化

通常は、フォームの Load イベント ハンドラー内にホスティング コードを実装します。 次のコードでは、Load イベント ハンドラー、WPF 複合コントロールの Loaded イベントのハンドラー、および後で使用するいくつかのグローバル変数の宣言を示します。

Windows フォーム デザイナーで、フォームをダブルクリックして Load イベント ハンドラーを作成します。 Form1.cs の先頭に、次の using ステートメントを追加します。

using System.Windows;
using System.Windows.Forms.Integration;
using System.Windows.Media;

既存の Form1 クラスの内容を次のコードに置き換えます。

private ElementHost ctrlHost;
private MyControls.MyControl1 wpfAddressCtrl;
System.Windows.FontWeight initFontWeight;
double initFontSize;
System.Windows.FontStyle initFontStyle;
System.Windows.Media.SolidColorBrush initBackBrush;
System.Windows.Media.SolidColorBrush initForeBrush;
System.Windows.Media.FontFamily initFontFamily;

public Form1()
{
    InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)
{
    ctrlHost = new ElementHost();
    ctrlHost.Dock = DockStyle.Fill;
    panel1.Controls.Add(ctrlHost);
    wpfAddressCtrl = new MyControls.MyControl1();
    wpfAddressCtrl.InitializeComponent();
    ctrlHost.Child = wpfAddressCtrl;

    wpfAddressCtrl.OnButtonClick +=
        new MyControls.MyControl1.MyControlEventHandler(
        avAddressCtrl_OnButtonClick);
    wpfAddressCtrl.Loaded += new RoutedEventHandler(
        avAddressCtrl_Loaded);
}

void avAddressCtrl_Loaded(object sender, EventArgs e)
{
    initBackBrush = (SolidColorBrush)wpfAddressCtrl.MyControl_Background;
    initForeBrush = wpfAddressCtrl.MyControl_Foreground;
    initFontFamily = wpfAddressCtrl.MyControl_FontFamily;
    initFontSize = wpfAddressCtrl.MyControl_FontSize;
    initFontWeight = wpfAddressCtrl.MyControl_FontWeight;
    initFontStyle = wpfAddressCtrl.MyControl_FontStyle;
}

前のコードの Form1_Load メソッドでは、WPF コントロールをホストするための一般的な手順が示されています。

  1. 新しい ElementHost オブジェクトを作成します。

  2. コントロールの Dock プロパティを DockStyle.Fill に設定します。

  3. ElementHost コントロールを Panel コントロールの Controls コレクションに追加します。

  4. WPF コントロールのインスタンスを作成します。

  5. ElementHost コントロールの Child プロパティにコントロールを割り当てることによって、フォーム上で複合コントロールをホストします。

Form1_Load メソッドの残りの 2 行では、2 つのコントロール イベントにハンドラーをアタッチします。

  • OnButtonClick は、ユーザーが [OK] または [Cancel] ボタンをクリックしたときに複合コントロールで生成されるカスタム イベントです。 このイベントを処理してユーザーの応答を取得し、ユーザーが指定したデータをすべて収集します。

  • Loaded は、完全に読み込まれた WPF コントロールによって生成される標準のイベントです。 ここでこのイベントを使用するのは、この例ではこのコントロールからのプロパティを使用して複数のグローバル変数を初期化する必要があるからです。 フォームの Load イベントの時点では、コントロールは完全には読み込まれておらず、これらの値はまだ null に設定されています。 それらのプロパティにアクセスするには、コントロールの Loaded イベントが発生するまで待つ必要があります。

Loaded イベント ハンドラーは、前のコードで示されています。 OnButtonClick ハンドラーについては次のセクションで説明します。

OnButtonClick の処理

OnButtonClick イベントは、ユーザーが [OK] または [Cancel] ボタンをクリックしたときに発生します。

イベント ハンドラーでは、イベント引数の IsOK フィールドがチェックされて、どちらのボタンがクリックされたかが特定されます。 lbldata 変数は、前に説明した Label コントロールに対応します。 ユーザーが [OK] ボタンをクリックすると、コントロールの TextBox コントロールからのデータは、対応する Label コントロールに割り当てられます。 ユーザーが [Cancel] をクリックすると、Text の値は既定の文字列に設定されます。

次のボタン クリック イベント ハンドラーのコードを Form1 クラスに追加します。

void avAddressCtrl_OnButtonClick(
    object sender,
    MyControls.MyControl1.MyControlEventArgs args)
{
    if (args.IsOK)
    {
        lblAddress.Text = "Street Address: " + args.MyStreetAddress;
        lblCity.Text = "City: " + args.MyCity;
        lblName.Text = "Name: " + args.MyName;
        lblState.Text = "State: " + args.MyState;
        lblZip.Text = "Zip: " + args.MyZip;
    }
    else
    {
        lblAddress.Text = "Street Address: ";
        lblCity.Text = "City: ";
        lblName.Text = "Name: ";
        lblState.Text = "State: ";
        lblZip.Text = "Zip: ";
    }
}

アプリケーションをビルドして実行します。 WPF 複合コントロールに任意のテキストを追加し、 [OK] をクリックします。 そのテキストがラベルに表示されます。 この時点で、オプション ボタンを処理するコードは追加されていません。

コントロールの外観の変更

フォームの RadioButton コントロールを使用すると、ユーザーは WPF 複合コントロールの前景と背景の色、およびいくつかのフォント プロパティを変更できます。 背景色は ElementHost オブジェクトによって公開されます。 残りのプロパティは、コントロールのカスタム プロパティとして公開されます。

フォーム上の各 RadioButton コントロールをダブルクリックして、CheckedChanged イベント ハンドラーを作成します。 CheckedChanged イベント ハンドラーを次のコードに置き換えます。

private void radioBackgroundOriginal_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_Background = initBackBrush;
}

private void radioBackgroundLightGreen_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_Background = new SolidColorBrush(Colors.LightGreen);
}

private void radioBackgroundLightSalmon_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_Background = new SolidColorBrush(Colors.LightSalmon);
}

private void radioForegroundOriginal_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_Foreground = initForeBrush;
}

private void radioForegroundRed_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_Foreground = new System.Windows.Media.SolidColorBrush(Colors.Red);
}

private void radioForegroundYellow_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_Foreground = new System.Windows.Media.SolidColorBrush(Colors.Yellow);
}

private void radioFamilyOriginal_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_FontFamily = initFontFamily;
}

private void radioFamilyTimes_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_FontFamily = new System.Windows.Media.FontFamily("Times New Roman");
}

private void radioFamilyWingDings_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_FontFamily = new System.Windows.Media.FontFamily("WingDings");
}

private void radioSizeOriginal_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_FontSize = initFontSize;
}

private void radioSizeTen_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_FontSize = 10;
}

private void radioSizeTwelve_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_FontSize = 12;
}

private void radioStyleOriginal_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_FontStyle = initFontStyle;
}

private void radioStyleItalic_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_FontStyle = System.Windows.FontStyles.Italic;
}

private void radioWeightOriginal_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_FontWeight = initFontWeight;
}

private void radioWeightBold_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_FontWeight = FontWeights.Bold;
}

アプリケーションをビルドして実行します。 別のオプション ボタンをクリックして、WPF 複合コントロール上の影響を確認します。

関連項目