元記事 (英語): Andrew Flick - http://community.infragistics.com/wpf/articles/hosting-a-wpf-control-in-a-windows-forms-application.aspx
Windows Forms アプリケーションで WPF コントロールをホストする
作業の開始 既存のアプリケーションを次世代アプリケーションに変換する開発方式の 1 つとして「WPF to Windows Forms Interop」があります。WPF はアプリケーションの視覚化で簡単に新しいユーザー エクスペリエンスを作成する機能を提供します。Windows Forms は、フレームワーク、ツール、そして長年の開発による高度な機能を提供します。Windows Forms のレガシー アプリケーションの情報を新しい方法で視覚化するには、Interop を使用します。 Infragistics WPF コントロールは情報の視覚化し、ナビゲーション項目を作成する新しい方法を提供します。存在の Windows Forms アプリケーションに WPF コントロールを追加できます。 参照の追加 統合の手順として、まず WPF コントロール (この例では XamDataPresenter) を Windows Forms アプリケーションに追加します。最初に WPF を処理する以下の Microsoft WPF アセンブリへの参照を追加する必要があります。 PresentationFramework PresentationCore WindowsBase WindowsFormsIntegration Microsoft アセンブリへの参照を追加した後に、以下の Infragistics アセンブリへの参照を追加します。 Infragistics3.Windows.DataPresenter.v7.1 Infragistics3.Windows.v7.1 Infragistics3.Windows.Editors.v7.1 Windows Forms アプリケーションの ElementHost で xamDataPresenter をホストする 次に、Windows Forms アプリケーションで WPF コントロールをホストするためのコードを追加します。このサンプルの場合、Form_Load イベントでコア ロジックを実行します。WPF コントロールなどの要素を含む ElementHost オブジェクトと呼ばれるコンテナーがこのコードで大切です。 XamDataPresenter のインスタンスを作成して DataSource プロパティを設定します。XamDataPresenter を ElementHost オブジェクトの子として関連付けます。コードは以下のようになります。 ... using System.Windows.Forms.Integration; ... namespace WindowsForms_WPF_InteropDemo { public partial class Main: Form { private ElementHost XamHost; private Infragistics.Windows.DataPresenter.XamDataPresenter XamDP; ... private void Form1_Load(object sender, EventArgs e) { XamHost = new ElementHost(); XamHost.Dock = DockStyle.Fill; this.Controls.Add(XamHost); XamDP = new Infragistics.Windows.DataPresenter.XamDataPresenter(); XamDP.DataSource = this.vSalesPersonSalesByFiscalYearsBindingSource; XamHost.Child = XamDP; } ... この実装は簡単で、数行のコードでフル XamDataPresenter オブジェクト モデルにアクセスできます。開発者は Visual Studio で XamDataPresenter コントロールを使用できます。 WPF のデザインと Windows Forms のビルド WPF 開発の核となる概念はデザインと開発を分けて考えることです。たとえば、XamDataPresenter を Blend でスタイル設定し、高度な UX を作成できます。Blend で「ダミー」コントロールにスタイルを設定して、Windows Forms プロジェクトに XAML コードをコピーできますが、効率的ではないため、2 つのツール環境のコミュニケーションを切り離します。WPF スタイル機能を完全に使用するには、他の方法を使用したほうがよいでしょう。 この問題を回避するには、XamDataPresenter をホストする WPF コントロール ライブラリを作成します。これによって、Blend でコントロールをスタイルでき、Visual Studio で ElementHost 内コントロールとして ControlLibrary をホストできます。(注: コントロール ライブラリを Blend でビルドできますが、テストまたは実行するには、ダミー プロジェクトに追加する必要があります。) 最初に問題となるのは、割り当てられたデータ ソースがないことです。これは、データソースとしてシンプルな XML ファイルを作成することで回避できます。そして、それを XamDataPresenter をスタイルために使用できます。あるいは、BindToSampleData プロパティを設定して、XamDataPresenter はサンプル データを使用して、コントロールのスタイル設定をカスタマイズできます。コントロールを視覚的にスタイル設定し、カスタム プレゼンターを追加するなどのデザイナー機能を使用できます。 デザインを変更した後に、プロジェクトをビルドして、Windows Forms ソリューションにプロジェクトを追加するか、Windows Forms プロジェクトの参照フォルダーにカスタム コントロールの DLL を追加します。 WPF プロパティを公開する Visual Studio では、上記で説明した方法で UserControl を要素ホストに関連付けます。そこで、DataSource プロパティが見つかりないという問題と、最初のサンプルの馴染みのあるプロパティが見つかりません。実際には、XamDataPresenter のプロパティの代わりに、UserControl のプロパティが表示されます。Blend でコントロールのスタイル設定が可能で、Visual Studio でコードを書けるとよいでしょう。このために、XamDataPresenter のプロパティを公開するコードを UserControl に追加する必要があります。 始めに、XamDataPresenter の DataSource プロパティにアクセスできるためのパブリック プロパティを UserControl に追加します。コードは以下のようになります。 public System.Collections.IEnumerable DataSource { get { return this.XamDataPresenterInternal.DataSource; } set { this.XamDataPresenterInternal.DataSource = value; } } WPF イベントへのリスナー UserControl のパブリック プロパティとして関連付けして、基本の XamDataPresenter の必要なプロパティを公開できます。また、基本プロジェクトにイベントを公開する必要もあります。このサンプルでは、グリッド セルの編集モードを終了する前にセル値を検証するイベントを追加します。Windows Forms アプリケーションで EditModeEndingEvent が使用できないため、Windows Forms アプリケーション内で基本 XamDataPresenter の EditModeEndingEvent を処理するパブリック イベントをユーザー コントロールに作成します。次のコードを xaml.cs ファイルに追加します。 public static RoutedEvent EditModeEndingEvent = EventManager.RegisterRoutedEvent ("EditModeEnding", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(XamDataPresenterWrapper)); public event RoutedEventHandler EditModeEnding { add { AddHandler(EditModeEndingEvent, value); } remove { RemoveHandler(EditModeEndingEvent, value); } } void XamDataPresenterInternal_EditModeEnding(object sender, Infragistics.Windows.DataPresenter.Events.EditModeEndingEventArgs e) { RaiseEvent(new RoutedEventArgs(XamDataPresenterWrapper.EditModeEndingEvent, e)); } .xaml ファイルでイベントを登録します。 <igDP:XamDataPresenter Name="XamDataPresenterInternal" EditModeEnding="XamDataPresenterInternal_EditModeEnding"/> WPF コントロール ライブラリを Windows Forms プロジェクトに接続する ControlLibrary で変更を処理したため、WPF プロジェクトをビルドして、Windows Forms プロジェクトに WPF アプリケーションを追加します。DataSource プロパティを設定します。 ... using System.Windows.Forms.Integration; ... namespace WindowsForms_WPF_InteropDemo { public partial class Main: Form { private ElementHost XamHost; private Infragistics.XamDataPresenterWrapper XamDataPresenter; ... private void Main_Load(object sender, EventArgs e) { ... XamHost = new ElementHost(); XamHost.Dock = DockStyle.Fill; this.Controls.Add(XamHost); XamDataPresenter = new Infragistics.XamDataPresenterWrapper(); XamDataPresenter.DataSource = this.vSalesPersonSalesByFiscalYearsBindingSource; XamHost.Child = XamDataPresenter; } ... その後で、イベントをフックして、そのイベントで処理するロジックを実行できます。このサンプルでは、イベント ハンドラーを (Main_Load) Form_Load イベントに追加して、必要なロジックを実行するコードを追加します。 ... using Infragistics.Windows.DataPresenter.Events; ... XamDataPresenter.EditModeEnding += new System.Windows.RoutedEventHandler(XamDataPresenter_EditModeEnding); ... void XamDataPresenter_EditModeEnding(object sender, System.Windows.RoutedEventArgs e) { // 編集モードの終了イベントの引数 EditModeEndingEventArgs editEndingArgs = e.OriginalSource as EditModeEndingEventArgs; if (editEndingArgs == null) return; // 編集しているフィールドの列名 (Infragistics.Windows.DataPresenter.Events) string columnName = editEndingArgs.Cell.Field.Name; // 編集した後のセル値 string newCellValue = editEndingArgs.Editor.Text; if (columnName == "Title" ) { // 新しいセル値が「Sales Representative」以外の値に変更された場合 if (newCellValue != "Sales Representative") { //変更を保存しません editEndingArgs.AcceptChanges = false; MessageBox.Show("Title Must Be Sales Representative"); } } } ... この場合では、「Sales Representative」セルが変更できないことを実装します。 リッチなクライアント エクスペリエンスを展開する この手順を完了したで、(アニメーションが表示されない) Windows Forms アプリケーション内で XamDataPresenter のグリッド ビューを表示するスクリーンショットはこれです。 また、このスクリーンショットは Windows Forms アプリケーション内でホストされる XamDataPresenter のカルーセル ビューを表示します。 タイプ依存関係についての注意 注: Windows Forms アプリケーションで Infragistics EditModeEndingEventArgs を使用しています。そのため、Infragistics WPF アセンブリへの参照が必要です。Infragistics WPF の依存関係が使用できない場合、リフレクションを使用できます。NetAdvantage WPF アセンブリの使用を推薦しますが、以下のコードも使用できます。 void XamDataPresenter_EditModeEnding(object sender, System.Windows.RoutedEventArgs e) { //編集したセル オブジェクトを検索します object cell = e.OriginalSource.GetType().GetProperty("Cell").GetValue( e.OriginalSource, null); //セルのフィールドを取得します object field = cell.GetType().GetProperty("Field").GetValue(cell, null); //セルのフィールド名を取得します string name = field.GetType().GetProperty("Name").GetValue(field, null) as string; //列名が「Title」かどうかを確認します if (name == "Title") { //ユーザーによって入力したテキストを取得します object editor = e.OriginalSource.GetType().GetProperty("Editor").GetValue( e.OriginalSource, null); string text = editor.GetType().GetProperty("Text").GetValue(editor, null) as string; //テキストが「Sales Representative」かどうかを確認します if (text != "Sales Representative") { e.OriginalSource.GetType().GetProperty("AcceptChanges").SetValue( e.OriginalSource, false, null); MessageBox.Show("Title Must Be Sales Representative"); } } } まとめ 開発者は、Infragistics が提供するスタイルを使用して、Visual Studio でアプリケーションを作成できます。グラフィック デザイナーがいるか、Blend との操作が必要な場合、コントロールをコントロール ライブラリにラップすることができます。ロールを分割することができます。 最後に、Interop の制限に注意してください。要素ホスト コントロールで 1 つの子コントロールのみがホストできます。WPF と Windows Forms には別のスケール モデルがあります。WindowsFormsHost で ElementHost をネストできない、また ElementHost で WindowsFormsHost をネストできません。制限のリストを表示するには、http://blogs.msdn.com/scoberry/archive/2006/09/01/735844.aspx (英語) を参照してください。. アプリケーションでリッチなクライアント エクスペリエンスを実現してください。
作業の開始
既存のアプリケーションを次世代アプリケーションに変換する開発方式の 1 つとして「WPF to Windows Forms Interop」があります。WPF はアプリケーションの視覚化で簡単に新しいユーザー エクスペリエンスを作成する機能を提供します。Windows Forms は、フレームワーク、ツール、そして長年の開発による高度な機能を提供します。Windows Forms のレガシー アプリケーションの情報を新しい方法で視覚化するには、Interop を使用します。
Infragistics WPF コントロールは情報の視覚化し、ナビゲーション項目を作成する新しい方法を提供します。存在の Windows Forms アプリケーションに WPF コントロールを追加できます。
参照の追加
統合の手順として、まず WPF コントロール (この例では XamDataPresenter) を Windows Forms アプリケーションに追加します。最初に WPF を処理する以下の Microsoft WPF アセンブリへの参照を追加する必要があります。
Microsoft アセンブリへの参照を追加した後に、以下の Infragistics アセンブリへの参照を追加します。
Windows Forms アプリケーションの ElementHost で xamDataPresenter をホストする
次に、Windows Forms アプリケーションで WPF コントロールをホストするためのコードを追加します。このサンプルの場合、Form_Load イベントでコア ロジックを実行します。WPF コントロールなどの要素を含む ElementHost オブジェクトと呼ばれるコンテナーがこのコードで大切です。
XamDataPresenter のインスタンスを作成して DataSource プロパティを設定します。XamDataPresenter を ElementHost オブジェクトの子として関連付けます。コードは以下のようになります。
この実装は簡単で、数行のコードでフル XamDataPresenter オブジェクト モデルにアクセスできます。開発者は Visual Studio で XamDataPresenter コントロールを使用できます。
WPF のデザインと Windows Forms のビルド
WPF 開発の核となる概念はデザインと開発を分けて考えることです。たとえば、XamDataPresenter を Blend でスタイル設定し、高度な UX を作成できます。Blend で「ダミー」コントロールにスタイルを設定して、Windows Forms プロジェクトに XAML コードをコピーできますが、効率的ではないため、2 つのツール環境のコミュニケーションを切り離します。WPF スタイル機能を完全に使用するには、他の方法を使用したほうがよいでしょう。
この問題を回避するには、XamDataPresenter をホストする WPF コントロール ライブラリを作成します。これによって、Blend でコントロールをスタイルでき、Visual Studio で ElementHost 内コントロールとして ControlLibrary をホストできます。(注: コントロール ライブラリを Blend でビルドできますが、テストまたは実行するには、ダミー プロジェクトに追加する必要があります。)
最初に問題となるのは、割り当てられたデータ ソースがないことです。これは、データソースとしてシンプルな XML ファイルを作成することで回避できます。そして、それを XamDataPresenter をスタイルために使用できます。あるいは、BindToSampleData プロパティを設定して、XamDataPresenter はサンプル データを使用して、コントロールのスタイル設定をカスタマイズできます。コントロールを視覚的にスタイル設定し、カスタム プレゼンターを追加するなどのデザイナー機能を使用できます。
デザインを変更した後に、プロジェクトをビルドして、Windows Forms ソリューションにプロジェクトを追加するか、Windows Forms プロジェクトの参照フォルダーにカスタム コントロールの DLL を追加します。
WPF プロパティを公開する
Visual Studio では、上記で説明した方法で UserControl を要素ホストに関連付けます。そこで、DataSource プロパティが見つかりないという問題と、最初のサンプルの馴染みのあるプロパティが見つかりません。実際には、XamDataPresenter のプロパティの代わりに、UserControl のプロパティが表示されます。Blend でコントロールのスタイル設定が可能で、Visual Studio でコードを書けるとよいでしょう。このために、XamDataPresenter のプロパティを公開するコードを UserControl に追加する必要があります。
始めに、XamDataPresenter の DataSource プロパティにアクセスできるためのパブリック プロパティを UserControl に追加します。コードは以下のようになります。
WPF イベントへのリスナー
UserControl のパブリック プロパティとして関連付けして、基本の XamDataPresenter の必要なプロパティを公開できます。また、基本プロジェクトにイベントを公開する必要もあります。このサンプルでは、グリッド セルの編集モードを終了する前にセル値を検証するイベントを追加します。Windows Forms アプリケーションで EditModeEndingEvent が使用できないため、Windows Forms アプリケーション内で基本 XamDataPresenter の EditModeEndingEvent を処理するパブリック イベントをユーザー コントロールに作成します。次のコードを xaml.cs ファイルに追加します。
.xaml ファイルでイベントを登録します。
WPF コントロール ライブラリを Windows Forms プロジェクトに接続する
ControlLibrary で変更を処理したため、WPF プロジェクトをビルドして、Windows Forms プロジェクトに WPF アプリケーションを追加します。DataSource プロパティを設定します。
その後で、イベントをフックして、そのイベントで処理するロジックを実行できます。このサンプルでは、イベント ハンドラーを (Main_Load) Form_Load イベントに追加して、必要なロジックを実行するコードを追加します。
この場合では、「Sales Representative」セルが変更できないことを実装します。
リッチなクライアント エクスペリエンスを展開する
この手順を完了したで、(アニメーションが表示されない) Windows Forms アプリケーション内で XamDataPresenter のグリッド ビューを表示するスクリーンショットはこれです。
また、このスクリーンショットは Windows Forms アプリケーション内でホストされる XamDataPresenter のカルーセル ビューを表示します。
タイプ依存関係についての注意
注: Windows Forms アプリケーションで Infragistics EditModeEndingEventArgs を使用しています。そのため、Infragistics WPF アセンブリへの参照が必要です。Infragistics WPF の依存関係が使用できない場合、リフレクションを使用できます。NetAdvantage WPF アセンブリの使用を推薦しますが、以下のコードも使用できます。
まとめ
開発者は、Infragistics が提供するスタイルを使用して、Visual Studio でアプリケーションを作成できます。グラフィック デザイナーがいるか、Blend との操作が必要な場合、コントロールをコントロール ライブラリにラップすることができます。ロールを分割することができます。
最後に、Interop の制限に注意してください。要素ホスト コントロールで 1 つの子コントロールのみがホストできます。WPF と Windows Forms には別のスケール モデルがあります。WindowsFormsHost で ElementHost をネストできない、また ElementHost で WindowsFormsHost をネストできません。制限のリストを表示するには、http://blogs.msdn.com/scoberry/archive/2006/09/01/735844.aspx (英語) を参照してください。.
アプリケーションでリッチなクライアント エクスペリエンスを実現してください。