WPFアプリのMainメソッドは通常、自動生成される。本稿では、Mainメソッドの自動生成をやめ、独自の処理を行うように書き換える方法を解説する。
対象:.NET 3.0以降
WPFでも、Mainメソッドを書き換えたいときがあるだろう。WPFの初期化処理が始まる前に何らかの処理を行いたいというときだ。コンソールプログラムならMainメソッドから書き始めるので、何の問題もない。Windowsフォームでは、Mainメソッドを記述したクラスをプロジェクトのプロパティで[スタートアップ オブジェクト]に指定すればよかった(参照:「.NET TIPS:VB.NETでアプリケーション起動時に実行されるフォームを変更するには?」/「.NET TIPS:C#でアプリケーション起動時に実行されるフォームを変更するには?」)。では、WPFではどのようにすればよいのだろうか? 本稿では、その方法を解説する。
WPFも、Windowsフォームと同様に、プロジェクトのプロパティで[スタートアップ オブジェクト]を指定できる*1。WPFの場合、既定ではAppクラス(C#)/Applicationクラス(VB)がスタートアップオブジェクトになっている。そして、WPFではそれらのクラスにMainメソッドが自動生成されるのである。それを確かめるには、Appクラス(C#)/Applicationクラス(VB)をコードエディターで開いて、上部のドロップダウンを開いてみると分かる(次の画像)。
*1 VBでは、[スタートアップ オブジェクト]の指定は少々分かりにくい。まず、[スタートアップ オブジェクト]を指定するには、[アプリケーション フレームワークを有効にする]のチェックを外す必要がある。チェックを外してみると[スタートアップ オブジェクト]には既定として[Sub Main]と表示されるが、ここで確認するようにそれはApplicationクラス内に自動生成されるものだ。ただし、今の段階でこのチェックを外してしまうと、自動生成されるMainメソッドを確認できなくなる。なお、この後、「Application.xaml」ファイルに対するビルドアクションを変更した時点で、このチェックは自動的に外れる。
このドロップダウンで[Main]を選択すると、自動生成されたMainメソッドが表示される。では、それを書き換えればよいかというと、そうはいかないのである。ビルドするたびに、自動生成コードで上書きされてしまうからだ。
そこで、まずはMainメソッドの自動生成を止めなければならない。それには、「App.xaml」ファイル(C#)/「Application.xaml」ファイル(VB)に対するビルドアクションを、他のXAMLファイルと同じく[Page]に変更すればよい(次の画像)。
続いて、Mainメソッドを追加する。「App.xaml.cs」ファイル(C#)/「Application.xaml.cs」ファイル(VB)を開いて、次のようなコードを追加すればよい。ただし、C#はこれだけでよいが、VBではビルドエラーになる(対応は後述)。
public partial class App : Application
{
[STAThread]
public static void Main()
{
App app = new App();
app.InitializeComponent();
app.Run();
}
}
Class Application
<STAThread> _
Public Shared Sub Main()
Dim app As Application = New Application()
app.InitializeComponent()
app.Run()
End Sub
End Class
プログラムの起動時に、何らかの条件(例えばコマンドライン引数など)によって最初に表示されるウィンドウを切り替えたいこともあるだろう。それをやってみよう。
この初期表示ウィンドウは、既定では「App.xaml」ファイル(C#)/「Application.xaml」ファイル(VB)に記述されている(次のコード)。
<Application x:Class="Application"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>
上のコードの「StartupUri="MainWindow.xaml"」の部分を削除し、先ほど作成したMainメソッドを次のコードのように書き換える。
[STAThread]
public static void Main()
{
App app = new App();
app.StartupUri = new Uri("MainWindow.xaml", UriKind.Relative);
app.InitializeComponent();
app.Run();
}
<STAThread> _
Public Shared Sub Main()
Dim app As Application = New Application()
app.StartupUri = New Uri("MainWindow.xaml", UriKind.Relative)
app.InitializeComponent()
app.Run()
End Sub
これでビルドして実行してみてほしい。ちゃんと「MainWindow.xaml」ウィンドウが表示されるはずだ。Mainメソッドを書き換えられるようにするという目標は、VBでも達成できた。
次にMainメソッドで初期表示ウィンドウを切り替えてみよう。プロジェクトにウィンドウを一つ追加してもらいたい。ファイル名は「SecondWindow.xaml」とする。プログラムの起動時にメッセージボックスを出し、エンドユーザーの応答によって初期表示ウィンドウを切り替えるコードは、次のように書ける。
[STAThread]
public static void Main()
{
var result = MessageBox.Show("SecondWindowを起動しますか?",
".NET TIPS #1119",
MessageBoxButton.YesNoCancel);
if (result == MessageBoxResult.Cancel)
return; // プログラム終了
App app = new App();
if (result == MessageBoxResult.Yes)
app.StartupUri = new Uri("SecondWindow.xaml", UriKind.Relative);
else
app.StartupUri = new Uri("MainWindow.xaml", UriKind.Relative);
app.InitializeComponent();
app.Run();
}
<STAThread> _
Public Shared Sub Main()
Dim result = MessageBox.Show("SecondWindowを起動しますか?",
".NET TIPS #1119",
MessageBoxButton.YesNoCancel)
If (result = MessageBoxResult.Cancel) Then
Return ' プログラム終了
End If
Dim app As Application = New Application()
If (result = MessageBoxResult.Yes) Then
app.StartupUri = New Uri("SecondWindow.xaml", UriKind.Relative)
Else
app.StartupUri = New Uri("MainWindow.xaml", UriKind.Relative)
End If
app.InitializeComponent()
app.Run()
End Sub
上のコードを実行すると、次の画像のようなメッセージボックスが表示される。[はい]ボタンをクリックすると「SecondWindow.xaml」のウィンドウが表示され、[いいえ]ボタンでは「MainWindow.xaml」のウィンドウが表示される。[キャンセル]ボタンでは、直ちにプログラムが終了する。
WPFでMainメソッドを書き変えるには、まず、「App.xaml」ファイル(C#)/「Application.xaml」ファイル(VB)の[ビルド アクション]を[Page]に変更し、それから、「App.xaml.cs」ファイル(C#)/「Application.xaml.cs」ファイル(VB)にMainメソッドを書き加える。VBでは、さらに、初期表示ウィンドウの指定をXAMLからMainメソッドに移す必要がある。
Mainメソッドのコーディングには、Appクラス(C#)/Applicationクラス(VB)の初期化処理が始まる前に任意の処理を実行できるというメリットがある。
利用可能バージョン:.NET Framework 3.0以降
カテゴリ:Visual Studio 処理対象:プロジェクト
カテゴリ:WPF/XAML 処理対象:アプリケーション
使用ライブラリ:Applicationクラス(System.Windows名前空間)
関連TIPS:VB.NETでアプリケーション起動時に実行されるフォームを変更するには?
関連TIPS:C#でアプリケーション起動時に実行されるフォームを変更するには?
関連TIPS:WPFでコマンドライン引数を取得するには?[C#、VB、2.0、3.0、3.5]
Copyright© Digital Advantage Corp. All Rights Reserved.