トップ回答者
WPFウィンドウをWindowsフォームの親に設定する

質問
-
WPFウィンドウで作成したクラス(System.Windows.Window)と、
Windowsフォームで作成したクラス(System.Windows.Forms.Form)を連携したいと思っています。
WPFのオブジェクトを親にして、Windowsフォームのオブジェクトの表示位置を親のセンターに合わせることが目的です。
WindowsフォームのSystem.Windows.Forms.Form.ParentをWPFのオブジェクトに設定したいのですが、型変換のエラーをどう解決すればいいのか見つかりませんでした。
過去ログなど検索したものの見つかりませんでしたので、もし同様の事例がありましたらリンクを紹介していただけると助かります。あるいは、解決策がありましたら教えてください。
回答
-
Form の Parent プロパティに設定できるのは System.Windows.Forms.Control 派生クラスだけです。
WPF の Window を Parent に設定することはできません。たとえば、次のような方法はどうでしょうか?
- WindowsFormsHost を貼り付けた、モーダル表示用の WPF Window を用意する。
- WindowsFormsHost の中に Form を配置する。Form は FormBorderStyle を None に、TopLevel を false にしておく。
- WindowsFormsHost を貼り付けた Window を ShowDialog で表示する。Window の Owner に親 Window を設定しておく。
既存の Form を WPF でモーダルダイアログっぽく表示できます。
なかむら(http://d.hatena.ne.jp/griefworker)
すべての返信
-
WindowsFormsHost を使ってはどうでしょう。
http://msdn.microsoft.com/ja-jp/library/ms742875.aspx
WindowsFormsHost を WPF Window のセンターに配置し、その中に Windows Forms のクラスを表示すればいいと思います。
なかむら(http://d.hatena.ne.jp/griefworker) -
WinForms から WPF を利用したいなら、次の記事が参考になるかもしれません。
http://d.hatena.ne.jp/hilapon/20100603/1275583609
なかむら(http://d.hatena.ne.jp/griefworker) -
なかむらさん、いつもありがとうございます。
なるほど、参照設定でプロジェクトを呼び出すのですね。
といってもどれもやったことがないので、まだ疑問は山積です。
じっさいにやってみて疑問が出てきたら、また整理してみます。
まずすぐ出てきた疑問は、このblogだと、FormにWPFのコントロールを配置していますが、Formから別ウィンドウでWPFのウィンドウを表示したいときにはどうしたらいいんでしょう、というのが疑問点です。private void wpfopenButton_Click(object sender, EventArgs e) {
Window wpfwindow = new Window();
Application application = new Application();
application.Run(wpfwindow);
}で開けるのだろうな、というのは考えていたのですが、このFormにコントロールを載せる方式だと、もうひとつFormを作るってことになるのかな、とか。
それよりは直接WPFのウィンドウを呼び出せたほうがいい気がする、というところとか。 -
Formから別ウィンドウでWPFのウィンドウを表示したいときにはどうしたらいいんでしょう、というのが疑問点です。
private void wpfopenButton_Click(object sender, EventArgs e) {
Window wpfwindow = new Window();
Application application = new Application();
application.Run(wpfwindow);
}で開けるのだろうな、というのは考えていたのですが、このFormにコントロールを載せる方式だと、もうひとつFormを作るってことになるのかな、とか。
それよりは直接WPFのウィンドウを呼び出せたほうがいい気がする、というところとか。
Appllication.Run は不要です。Window.ShowDialog() で起動するだけです。
private void wpfopenButton_Click(object sender, EventArgs e) { Window wpfwindow = new Window(); ElementHost.EnableModelessKeyboardInterop(window); wpfwindow.ShowDialog(); }
これで起動できます。でも相互運用はひとつ落とし穴があるので、以下の記事を参考にしてください。
http://d.hatena.ne.jp/hilapon/20100618/1276855276
また勘違いしやすいところですが、参照設定をきちんと追加すれば、プロジェクトを分けなくても WPF と WinForms は混在可能です。(あまり実用的でなく、本来プロジェクトをきちんと分けた方がいいですが、技術的には混在可能という程度の話です)
ひらぽん http://d.hatena.ne.jp/hilapon/
- 編集済み ひらぽんModerator 2010年9月20日 4:45 タグの微調整
-
WindowsFormsHost を使ってはどうでしょう。
http://msdn.microsoft.com/ja-jp/library/ms742875.aspx
WindowsFormsHost を WPF Window のセンターに配置し、その中に Windows Forms のクラスを表示すればいいと思います。
なかむら(http://d.hatena.ne.jp/griefworker)
早速の情報提供ありがとうございます。
ただし、この方法はすでに知っていますし、私のやりたいことではありません。
たとえば、下記のコード。Form1 form = new Form1();
form.Parent = this; // WPFウィンドウ
form.ShowDialog();このように、Windowsフォームを別ウインドウとしてモーダルに実行したいのです。
なかむらさんの方法では、WPFウィンドウの中に埋め込まれた状態で表示されてしまうためウインドウが移動できず、やはりやりたい事とは違います。残念ですが、これは回答ではありません。
-
Form の Parent プロパティに設定できるのは System.Windows.Forms.Control 派生クラスだけです。
WPF の Window を Parent に設定することはできません。たとえば、次のような方法はどうでしょうか?
- WindowsFormsHost を貼り付けた、モーダル表示用の WPF Window を用意する。
- WindowsFormsHost の中に Form を配置する。Form は FormBorderStyle を None に、TopLevel を false にしておく。
- WindowsFormsHost を貼り付けた Window を ShowDialog で表示する。Window の Owner に親 Window を設定しておく。
既存の Form を WPF でモーダルダイアログっぽく表示できます。
なかむら(http://d.hatena.ne.jp/griefworker) -
もう解決されてるようですが、タイトルが 「WPF ウィンドウを Windows フォームの親に設定する」 なだけに今後このスレを読まれる方もいるでしょうから、二点だけ気になった点を書かせて頂きます。
まず Form と Window の連携ですが、今回のように
> WPFのオブジェクトを親にして、Windowsフォームのオブジェクトの表示位置を親のセンターに合わせることが目的です。
だけなら、無理に Parent に設定せずとも、以下のように画面表示位置のデータを子ウィンドウに渡してやるだけでいいと思います。
using System.Windows; using System.Windows.Forms; namespace WpfApplication1 { /// <summary> /// MainWindow.xaml の相互作用ロジック /// </summary> public partial class MainWindow : Window { // Windows フォーム class Form1 : Form { } public MainWindow() { InitializeComponent(); } private void button1_Click(object sender, RoutedEventArgs e) { WindowsFormsHost.EnableWindowsFormsInterop(); using (Form1 form = new Form1()) { System.Drawing.Point pt = new System.Drawing.Point((int)this.Left, (int)this.Top); form.Location = pt; form.StartPosition = FormStartPosition.Manual; form.ShowDialog(); } } } }
もしくは 子Form 側に、仮に ParentWindow プロパティを持たせるという解もあります。public class Form2 : Form { Window _window; public Window ParentWindow { get { return _window; } set { _window = value; } } protected override void OnLoad(System.EventArgs e) { base.OnLoad(e); this.Location = new System.Drawing.Point((int)_window.Left, (int)_window.Top); this.StartPosition = FormStartPosition.Manual; } }
> WPFのプロジェクトにWindowsフォームは混在しないほうがよいという結論のようですね。
>(技術的には可能のようですが。)理想的にはそうで しょうね。ただし既存資産との連携や ActiveX との連携が避けられない場合、 WindowsForms と WPF の相互運用は有効であると思っています。
またすでに稼働中の WindowsForms プロジェクトを WPF に移行する場合、いっぺんに移行するより徐々に WPF に移行するのも有効な方法であると思っております。ちなみに私が現在携わっているプロジェクトは WindowsForms プロジェクトですが、画面の一部を WPF に移行しております。すでに本番環境で稼働しており、10 社以上において 2 か月近く XP・Vista・7 と多様な環境で動作しておりますが、相互運用が原因と思われる不具合は、現時点まだ上がってきておりません。
#あくまで参考までにどうぞ。
ひらぽん http://d.hatena.ne.jp/hilapon/