none
WPFウィンドウをWindowsフォームの親に設定する RRS feed

  • 質問

  • WPFウィンドウで作成したクラス(System.Windows.Window)と、

    Windowsフォームで作成したクラス(System.Windows.Forms.Form)を連携したいと思っています。

    WPFのオブジェクトを親にして、Windowsフォームのオブジェクトの表示位置を親のセンターに合わせることが目的です。

    WindowsフォームのSystem.Windows.Forms.Form.ParentをWPFのオブジェクトに設定したいのですが、型変換のエラーをどう解決すればいいのか見つかりませんでした。

    過去ログなど検索したものの見つかりませんでしたので、もし同様の事例がありましたらリンクを紹介していただけると助かります。あるいは、解決策がありましたら教えてください。

    2010年9月17日 8:05

回答

  • Form の Parent プロパティに設定できるのは System.Windows.Forms.Control 派生クラスだけです。
    WPF の Window を Parent に設定することはできません。

    たとえば、次のような方法はどうでしょうか?

    1. WindowsFormsHost を貼り付けた、モーダル表示用の WPF Window を用意する。
    2. WindowsFormsHost の中に Form を配置する。Form は FormBorderStyle を None に、TopLevel を false にしておく。
    3. WindowsFormsHost を貼り付けた Window を ShowDialog で表示する。Window の Owner に親 Window を設定しておく。

    既存の Form を WPF でモーダルダイアログっぽく表示できます。

     

     


    なかむら(http://d.hatena.ne.jp/griefworker)
    • 回答としてマーク yoichiro 2010年9月24日 4:02
    • 回答としてマークされていない yoichiro 2010年9月24日 4:03
    • 回答としてマーク yoichiro 2010年9月24日 4:06
    2010年9月22日 6:37

すべての返信

  • WindowsFormsHost を使ってはどうでしょう。

    http://msdn.microsoft.com/ja-jp/library/ms742875.aspx

    WindowsFormsHost を WPF Window のセンターに配置し、その中に Windows Forms のクラスを表示すればいいと思います。

     


    なかむら(http://d.hatena.ne.jp/griefworker)
    2010年9月17日 8:47
  • 同じようなシチュエーションで逆の方法で困っています。
    FormにWPFを連携したいのです。
    同様に、型変換のエラーが大量に出ています。
    大量といっても、100個前後なので、置換すれば足りる範囲ではあるのですが、ややめんどうでもあります。
    この場合にはどうしたらよいでしょう?
    2010年9月19日 10:32
  • WinForms から WPF を利用したいなら、次の記事が参考になるかもしれません。

    http://d.hatena.ne.jp/hilapon/20100603/1275583609

     


    なかむら(http://d.hatena.ne.jp/griefworker)
    2010年9月19日 11:05
  • なかむらさん、いつもありがとうございます。
    なるほど、参照設定でプロジェクトを呼び出すのですね。
    といってもどれもやったことがないので、まだ疑問は山積です。
    じっさいにやってみて疑問が出てきたら、また整理してみます。
    まずすぐ出てきた疑問は、この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のウィンドウを呼び出せたほうがいい気がする、というところとか。

    2010年9月20日 4:21
  • 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/

    2010年9月20日 4:41
    モデレータ
  • 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ウィンドウの中に埋め込まれた状態で表示されてしまうためウインドウが移動できず、やはりやりたい事とは違います。

    残念ですが、これは回答ではありません。

    2010年9月21日 23:36
  • Form の Parent プロパティに設定できるのは System.Windows.Forms.Control 派生クラスだけです。
    WPF の Window を Parent に設定することはできません。

    たとえば、次のような方法はどうでしょうか?

    1. WindowsFormsHost を貼り付けた、モーダル表示用の WPF Window を用意する。
    2. WindowsFormsHost の中に Form を配置する。Form は FormBorderStyle を None に、TopLevel を false にしておく。
    3. WindowsFormsHost を貼り付けた Window を ShowDialog で表示する。Window の Owner に親 Window を設定しておく。

    既存の Form を WPF でモーダルダイアログっぽく表示できます。

     

     


    なかむら(http://d.hatena.ne.jp/griefworker)
    • 回答としてマーク yoichiro 2010年9月24日 4:02
    • 回答としてマークされていない yoichiro 2010年9月24日 4:03
    • 回答としてマーク yoichiro 2010年9月24日 4:06
    2010年9月22日 6:37
  • WPFのプロジェクトにWindowsフォームは混在しないほうがよいという結論のようですね。
    (技術的には可能のようですが。)

    なかむらさんのような方法で混在に関する問題を回避するのが最適解のようですので、これにて議論を終結します。

    2010年9月24日 4:06
  • もう解決されてるようですが、タイトルが 「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/
    2010年9月24日 9:35
    モデレータ