Share via


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

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

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

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

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

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

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

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

必要条件

このチュートリアルを実行するには、次のコンポーネントが必要です。

  • Visual Studio 2010

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

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

WPF 複合コントロール

単純な WPF コントロール

プロジェクトの作成

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

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

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

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

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

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

  6. ソリューション エクスプローラーで、UserControl1 の名前を MyControl1 に変更します。

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

  • PresentationCore

  • PresentationFramework

  • System

  • WindowsBase

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

複合コントロールのuser interface (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="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="https://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 のスタイルの詳細については、「スタイルとテンプレート」を参照してください。

複合コントロールの Style 要素を次の XAML に示します。 スタイルが要素にどのように適用されるかについては、前の 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] および [Cancel] ボタンの追加

複合コントロール上の最後の要素は、Grid の最後の行の最初の 2 つの列を専有する [OK] および [Cancel]Button 要素です。 これらの要素は、共通のイベント ハンドラーである 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 Forms コントロールをホストするために使用される WindowsFormsHost クラスとは異なり、ElementHost クラスはコントロールの Background プロパティのみを公開します。 このコード例と「チュートリアル: WPF での Windows フォーム複合コントロールのホスト」で説明した例の類似性を保持するために、このコントロールでは残りのプロパティを直接公開します。

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

分離コード ファイルは、MyControl1 および MyControlEventArgs という 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 Forms ホスト アプリケーションは 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

    Times New Roman

    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;
using System.Windows;
using System.Windows.Navigation;
using System.Windows.Controls;
using System.Windows.Media;

namespace MyControls
{
    public partial class MyControl1 : Grid
    {
        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;
        }

        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);
        }

        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;
            }
        }
    }

    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; }
        }
    }
}
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 複合コントロール上の影響を確認します。

参照

処理手順

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

参照

ElementHost

WindowsFormsHost

概念

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

その他の技術情報

WPF デザイナー