trapemiyaの日記

hatenablogが新しくなったんで新規一転また2019年1月からちょこちょこ書いてます。C#中心のプログラミングに関するお話です。

Windows FormプロジェクトにWPFプロジェクトで開発して機能を追加する

Window Formプロジェクトのアプリがあり、それに機能を追加する案件が発生しました。今更Windows Formで開発したくもなく、かといってWPFプロジェクトで全て作り直すのもアホらしいのです。
で、新規開発はWPFプロジェクトで作成し、それをWindows Formプロジェクトと合体させ、ユーザーから見ればシームレスに見えるように開発することにしました。
いろいろ試したところ、WPFプロジェクトを新しく作成し、そこからWindows Formプロジェクトを参照登録し、WPFプロジェクトからWindows Formプロジェクトの初期画面を表示するようにするとうまく行きました。といってもちょっとしたコツが要りますので、それを書いておきます。

まず、ダミーのWPFプロジェクトを作成し、そのApp.xamlのビルドアクションをApplicationDifinitionからPageにしてMainメソッドの自動生成を止め、App.xaml.csのAppクラスにMainメソッドを追加し、以下のようにWindows FormアプリケーションのMainメソッドを呼べば、Windows Formの初期画面が開きます。AppクラスのInitializeComponentメソッドを実行する必要があるようです。
参照設定としては、Windows FormプロジェクトとSystem.Windows.Formsが必要です。また、App.xamlからStartupUri="MainWindow.xaml"を削除する必要があります。

[STAThread]
public static void Main()
{
    App app = new App();
   //app.StartupUri = new Uri("MainWindow.xaml", UriKind.Relative);
   app.InitializeComponent();
   //app.Run();
   hoge.fuga.Main(null);
}

ここで注意が必要なのが、Windows FormアプリからWPFアプリの画面を開いて閉じると、そこでWPFのアプリが終わってしまいます。よって、次にWPFの画面を開こうとするとこけます。
結局、画面を閉じないようにしなければダメっぽいので、

[STAThread]
public static void Main()
{
   App app = new App();
   app.StartupUri = new Uri("MainWindow.xaml", UriKind.Relative);
   app.InitializeComponent();
   //app.Run();
   hoge.fuga.Main(null);
}

とし、

public MainWindow()
{
   InitializeComponent();
   this.Visibility = Visibility.Hidden;
}

として、MainWindowを非表示にして残し続けてやれば良いようである。