この質問に何回も答えても謝りますが、私にとってはうまくいく答えが見つからないようです。私は、アプリケーションが長時間実行されているタスクを実行している間、さまざまな進行状況メッセージを表示するモーダルウィンドウを作成したいと考えています。これらのタスクは別のスレッドで実行され、プロセスのさまざまな段階で進行状況ウィンドウのテキストを更新できます。クロススレッド通信はすべてうまく動作しています。問題は、ウィンドウを他のアプリケーションウィンドウ(コンピュータのすべてのアプリケーションではなく)の上に置くことができず、上に留まり、親ウィンドウとのやりとりを防ぎ、作業を続けることができないということです。ここでWPFモーダル進捗ウィンドウ
は、私がこれまで試したものです:
はまず、私のスプラッシュウィンドウはウィンドウクラスを拡張し、メッセージボックスを更新するためのメソッドを持つカスタムクラスです。私はスプラッシュクラスの新しいインスタンスを早期に作成し、必要に応じて表示/非表示にします。例最も単純で
、私は窓をインスタンス化し、その上に.Show()
を呼び出す:これは正しくウィンドウが表示され、初期化タスクを処理するための私のコードを実行し続け
//from inside my secondary thread
this._splash.Dispatcher.Invoke(new Action(() => this._splash.Show());
//Do things
//update splash text
//Do more things
//close the splash when done
this._splash.Dispatcher.Invoke(new Action(() => this._splash.Hide());
を、それは私が上でクリックすることができます親ウィンドウを前面に持ってきてください。
次は私がメインウィンドウを無効にし、後で再有効化しようとした:
Application.Current.Dispatcher.Invoke(new Action(() => this.MainWindow.IsEnabled = false));
//show splash, do things, etc
Application.Current.Dispatcher.Invoke(new Action(() => this.MainWindow.IsEnabled = true));
これは、ウィンドウ内のすべての要素を無効にしますが、私はまだメインウィンドウをクリックして、スプラッシュスクリーンの前でそれを持って来ることができますそれは私が望むものではありません。
次へスプラッシュウィンドウの一番上のプロパティを使用してみました。これはすべての前にそれを保持し、メインウィンドウのIsEnabledプロパティを設定することと関連して、私は対話を防ぐことができますが、スプラッシュ画面が他のアプリケーションを含めてすべての前面に表示されます。私はそれも望んでいない。私はこのアプリケーションの中で一番上のウィンドウにしたいだけです。
次に、.Show()
の代わりに.ShowDialog()
を使用することについての投稿が見つかりました。私はこれを試して、それは正しくダイアログを示して、私は親ウィンドウをクリックすることを許可しませんでしたが、.ShowDialog()
を呼び出すと、コードを実行し続ける前にダイアログを閉じるのを待っているプログラムがハングアップします。これは明らかに私が望むものではありません。私は別のスレッドでShowDialog()
と呼ぶことができると思います。そのスレッドはハングアップしますが、スレッドは作業をしません。これは推奨される方法ですか?
私はまた、ウィンドウをまったく使用せず、その代わりにフルサイズのウィンドウ要素をページの他のものの前に置くことも考えました。これは私が開いている他のウィンドウがあることを除いて動作し、それらも開いているときにスプラッシュスクリーンを使用できるようにしたいと思います。ウィンドウ要素を使用した場合、すべてのウィンドウでそれを再作成する必要があり、私のカスタムスプラッシュクラスで便利なUpdateSplashText
メソッドを使用することはできません。
これは私に質問につながります。これを処理する正しい方法は何ですか?
お時間をありがとうと長い質問には申し訳ありませんが、詳細は重要です:)
:
これは、このようなものと言えるでしょう。 "ShowDialog"を呼び出すことによって作成されたモダリティは完璧ですが、私は実行を停止しないために必要でした。 – BrianVPS