私はVisual StudioでのWinFormsプログラミングに慣れていますが、WPFを試してみたいと思いました。
プロジェクトにWindow01という別のウィンドウを追加しました。メインウィンドウはMainWindowと呼ばれます。 public MainWindow()
コンストラクターの前に、Window01を宣言します。
_Window01 w1;
_
次に、このウィンドウを次の場所でインスタンス化します。
_private void Window_Loaded(object sender, RoutedEventArgs e)
{
w1 = new Window01();
}
_
ウィンドウが表示されるボタンw1.ShowDialog();
があります。
ここでの「面白い」ことは、アプリケーションを(デバッグを使用して)開始し、数秒後にアプリケーションを終了した場合(アプリケーションで何もしない)、Visual Studioはアプリケーションがまだ実行されています。
行w1 = new Window01();
をボタンクリックメソッド、つまりShowDialog()
のすぐ上に移動すると、Visual Studioは正常に動作します。つまり、アプリケーションを終了するとデバッグが停止します。
なぜこの奇妙な振る舞いですか?
あなたのMainWindow.xaml.cs
、これを試してください:
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
Application.Current.Shutdown();
}
このリンクごとに、XAMLでShutdownMode
を設定することもできます。
http://msdn.Microsoft.com/en-us/library/system.windows.application.shutdownmode.aspx
<Application
xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.Microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml"
ShutdownMode="OnExplicitShutdown"
>
</Application>
アプリケーションは、Shutdown
のApplication
メソッドが呼び出されたときにのみ実行を停止します。シャットダウンは、ShutdownMode
プロパティの値で指定されているように、暗黙的または明示的に発生します。
ShutdownMode
をOnLastWindowClose
に設定すると、現在インスタンス化されているウィンドウがメインウィンドウとして設定されている場合でも、Windows Presentation Foundation(WPF)はアプリケーションの最後のウィンドウが閉じたときに暗黙的にShutdownを呼び出します(MainWindow )。
ShutdownMode
のOnMainWindowClose
により、他のウィンドウが現在開いている場合でも、MainWindowが閉じるとWPFが暗黙的にShutdownを呼び出します。
一部のアプリケーションの有効期間は、メインウィンドウまたは最後のウィンドウがいつ閉じられたかに依存していないか、ウィンドウにまったく依存していない可能性があります。これらのシナリオでは、ShutdownMode
プロパティをOnExplicitShutdown
に設定する必要があり、アプリケーションを停止するには明示的なShutdown
メソッド呼び出しが必要です。それ以外の場合、アプリケーションはバックグラウンドで実行され続けます。
ShutdownMode
は、XAMLから宣言的に構成するか、コードからプログラムで構成できます。
このプロパティは、Application
オブジェクトを作成したスレッドからのみ使用できます。
あなたの場合、おそらくデフォルトのOnLastWindowClose
を使用しているため、アプリは閉じません。
ShutdownMode
をOnLastWindowClose
に設定すると、現在インスタンス化されているウィンドウがメインウィンドウとして設定されている場合でも、WPFはアプリケーションの最後のウィンドウが閉じるときに暗黙的にShutdownを呼び出します(MainWindow
)。
新しいウィンドウを開いており、閉じていないので、シャットダウンは呼び出されません。
回答が得られたことをうれしく思いますが、他の人のために、いくつかの情報を追加するためにあなたの質問にも答えます。
まず、メインウィンドウが閉じたときにプログラムを終了する場合は、この動作がデフォルトのWinFormsではないため、指定する必要があります。
(WPFのデフォルトは、最後のウィンドウが閉じたときです)
コード内
エントリポイントでアプリケーションインスタンスに移動します(VS 2012のWPFプログラムでは、デフォルトはApp.xaml
ので、insideに行き、App.xaml.cs
&コンストラクターを作成します)。
コンストラクターで、 Application
の ShutdownMode
が ShutdownMode
であることを指定します .OnLastWindowClose
。
public App()
{
ShutdownMode = ShutdownMode.OnLastWindowClose;
}
XAMLで
App.xaml
VS 2012がデフォルトで作成した(または自分で作成した)ルートはApplication
であり、 Application
の ShutdownMode
は ShutdownMode
.OnLastWindowClose
でなければなりません。
<Application x:Class="WpfApplication27.App"
xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.Microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml"
ShutdownMode="OnMainWindowClose">
動作する場合、完了です。読むのをやめることができます。
上記が機能しなかった場合(WPFアプリケーションをゼロから作成したと思います)、メインウィンドウはおそらくアプリケーションにメインウィンドウとして認識されていません。したがって、そのように指定します。
コード内
手順1で行ったようにアプリケーションのコンストラクターに移動し、 Application
。 MainWindow
の値があなたの Window
:
MainWindow = mainWindow;
XAMLで
手順1で行ったようにApplication
XAMLに移動し、 Application
。 MainWindow
を指定しますの値はあなたの Window
です:
MainWindow = "mainWindow";
WPFがあなたにこれを望んでいないという理由だけで、これが最善のアプローチだとは思いません(したがって、 Application
's ShutdownMode
)、ただし、イベントを使用するだけで、イベントメソッドをオーバーライドできます(OnEventHappened)。
MainWindowの分離コードファイルに移動して、以下を追加します。
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
App.Current.Shutdown();
}
WPFアプリケーションのデフォルトの シャットダウンモード はOnLastWindowCloseであるため、最後のウィンドウが閉じるとアプリケーションが停止します。
新しいWindowオブジェクトをインスタンス化すると、アプリケーションの windowsのリスト に自動的に追加されます。したがって、問題は、アプリケーションが起動時に2つのウィンドウ(MainWindowとまだ表示されていないWindow01)を作成し、MainWindowを閉じただけの場合、Window01がアプリケーションを実行し続けることでした。
通常、ShowDialogを呼び出すのと同じメソッドでウィンドウオブジェクトを作成し、ダイアログが表示されるたびに新しいウィンドウオブジェクトを作成します。
他の何かを探しているときにこの質問に出くわし、Window.Owner
について言及している提案された回答のどれも見られなかったことに驚きました。
{
var newWindow = new AdditionalWindow();
newWindow.Owner = Window.GetWindow(this);
// then later on show the window with Show() or ShowDialog()
}
Window.GetWindow(this)
の呼び出しは、MVVMアプリケーションのビューで、インスタンス化された場所がわからないビジュアルツリーをはるかに下回っている場合に非常に便利です。FrameWork
要素(たとえばUserContol
、Button
、Page
)。明らかに、ウィンドウへの直接参照がある場合は、それまたはApplication.Current.MainWindow
を使用します。
これは非常に強力な関係であり、最初は気付かないかもしれない多くの有用な利点があります(これらの関係を回避するために個別のウィンドウを具体的にコーディングしていないと仮定します)。
メインウィンドウをMainWindow
、2番目のウィンドウをAdditionalWindow
として呼び出すと、...
MainWindow
を最小化すると、AdditionalWindow
も最小化されますMainWindow
を復元すると、AdditionalWindow
も復元されますMainWindow
を閉じるとAdditionalWindow
が閉じますが、AdditionalWindow
を閉じてもMainWindow
は閉じません。AdditioanlWindow
はMainWindow
の下で「失われる」ことはありません。つまり、Show()
を使用すると、AddditionalWindow
は常にzオーダーでMainWindow
の上に表示されますそれを表示するには(非常に便利!)ただし、この関係がある場合、Closing
のAdditionalWindow
イベントは呼び出されないため、OwnedWindows
コレクションを手動で反復処理する必要があります。 。例えば新しいインターフェイスまたは基本クラスメソッドを介して各ウィンドウを呼び出す方法を作成します。
private void MainWindow_OnClosing(object sender, CancelEventArgs e)
{
foreach (var window in OwnedWindows)
{
var win = window as ICanCancelClosing; // a new interface you have to create
e.Cancel |= win.DoYouWantToCancelClosing();
}
}
ダイアログボックスとして機能する2つ目のウィンドウを作成したときに遭遇したように見えます。 2番目のウィンドウを開いてから閉じてからメインウィンドウを閉じても、アプリは(バックグラウンドで)実行を続けました。 App.xamlに以下を追加(または確認)しました。
<Application x:Class="XXXXXXX.App"
...
StartupUri="MainWindow.xaml"
ShutdownMode="OnMainWindowClose">
<Application.MainWindow >
<NavigationWindow Source="MainWindow.xaml" Visibility="Visible" />
</Application.MainWindow>
喜びはありません。
そこで、ようやく「MainWindow.xaml」に入り、「Closed」プロパティをWindowに追加し、次のような「MainWind_Closed」メソッドに進みました。
private void MainWind_Closed(object sender, EventArgs e)
{
foreach ( Window w in App.Current.Windows )
{
if (w.DataContext != this)
w.Close();
}
}
デバッガーを実行すると、表示される唯一のウィンドウはダイアログとして作成したウィンドウであるように見えます。つまり、foreachループはメインではなくダイアログを1つだけ検索します。
ダイアログを閉じるメソッドで「this.Close()」を実行していましたが、「dlgwin.ShowDialog()」の後に「dlgwin.Close()」があり、動作しませんでした。 「dlgwin = null」でもありません。
それでは、この余分なものがなければダイアログが閉じないのはなぜですか?しかたがない。これは動作します。