WPFを使う-ShowとVisibilityの違い

初めに

質問掲示板で、StartupUriでxamlを指定して表示した場合と、new Window+ Showで表示した場合に、動作の違いがあるのはなぜですか?というのが掲載されていた。

途中、変なコメントだけ入れてしまった人がいたため、なんかグダグダな状態で解決となってしまっていた。個人的にも理由が知りたかったのでちょっと調べてみた。

質問内容

NavigationWindowにsourceを付け、画面センターに表示させる設定をしたものをxamlで定義する。

  1. これをStartupUriで指定した場合は、想定通りウィンドウ中心が画面中心に表示された
  2. ただし、このWindowをNewしてその後Showをすると、ウィンドウの左上が画面中心になった

というもの。

ShowとStartupUriで動作がどう違うのか

デバッガで追っていくと、2番目は、まずsourceの中身がない状態でウィンドウが表示された。その後sourceの中身が挿入された。そのため、sourceの中身がない状態で、ウィンドウの位置計算がされたので、想定した位置になっていなかったようだ。

NavigationWindow関連のイベントを見ると、次のような順番で呼びされていた。

StartupUrl New + Show
app.Run
  navigating
  initialized
  navigated
  loadcompleted
  isvisiblechanged
  loaded
  sourceinitialized
  activated
  isvisiblechanged
New(InitializeComponent)
 navigating
 initialized
Show
  isvisiblechanged
  loaded
  sourceinitialized
  activated
app.Run
  navigated
  loadcompleted
  isvisiblechanged

ちなみに、赤い字の部分は、プログラム側で実装したコード、黒いのがイベント。

これを見ると、StartupUrlでは、表示される前段階で、ナビゲート部品が配置され、その状態でウィンドウサイズの計算がされていたものと思われるが、New+Showでは、Showのタイミングでは、ナビゲート部品が配置されておらず、その状態でウィンドウサイズの計算と表示がされている。

そのため、表示位置に違いが出たものと思われる。

ウィンドウの表示方法について

WPFウィンドウの概要ではStartupUrlかShowで表示するような記述になっており、あたかもどちらでも利用可能なような記述になっており、またどちらも同じ動作かの印象を与えている。まあ、StartupUrlは内部でShow相当をしてますよ、てな感じなのだが。

ただ、Window.Showの記述には第3の記述方法としてVisibilityでも設定可能というような記述があった。

ShowとVisibilityは同期か非同期化の違い。

これが、どのように動作に影響を及ぼすのかは、MSDNではLoadedのイベント処理でしか表していなかった。ただ今回、表示方法をShowからVisibility = Visibility.Visibleに変更すると、StartupUrlと同じ動作になった。

結果

今回の件だけ見ると、Showを使うのではなく、Visibilityでの表示・非表示の設定のほうがいいのではないかと思った。

NavigationWindowのイベントの例を見る限り、実効順序を守らなければいけない非同期?の処理があるようなので、Showを使うのは相当切羽詰まった状態じゃないといけないのだろう。

コメント

タイトルとURLをコピーしました