2009-11-16 27 views
9

SizeToContentWidthAndHeightに設定すると、WindowStartupLocation="CenterOwner"が正しく動作しません。新しいウィンドウの中心が親のオーナーの中心になるのではなく、子ウィンドウの左上の角のように親の中心にくるように見えます。 SizeToContentを削除しても問題ありません。 どうしたのですか?wpfセンターの子ウィンドウがsizetocontentで動作しない

答えて

6

ウィンドウを、私はあなたが忘れすることができることを考えることができ

唯一のものは、実際にその所有者である子ウィンドウを伝えることですそれが測定されると、WindowStartupLocationは、測定プロセスによって計算されたウィンドウのActualWidthおよびActualHeightを使用して処理されます。

ActualWidthActualHeightは、Show()またはShowDialog()呼び出し時にゼロまたは比較的小さく測定され、後ではゼロ以外の値に設定されることがわかります。

たとえば、ウィンドウのコンテンツがLoadedイベントでのみ設定されたDataContextを使用して構築されている場合に発生します。 Show()が呼び出されると、ウィンドウはまだLoadedになっていないので、データはありません。後でLoadedイベントが発生すると、DataContextが設定され、ウィンドウのコンテンツは更新されますが、位置付けは既に発生しています。

Dispatcher.BeginInvoke呼び出しを使用してコンテンツを埋め込んだり、別のスレッドからコンテンツを埋め込んだり、遅延または非同期のバインディングを使用したりするなど、さまざまなシナリオがあります。

基本的には、Show()が呼び出された瞬間にウィンドウの内容が通常より小さくなる可能性のあるものを探して修正する必要があります。

+0

ありがとう、私は実際Show()の直後にコンテンツをロードしていました。愚かな間違いは、今うまく動作:) – immuner

1

あなたの質問は少し曖昧です。 SizeToContentとWindowStartupLocationをどちらのウィンドウ(「親」または「子」)で設定していますか?

私のプロジェクトで2番目のウィンドウを作成し、そのSizeToContentとWindowStartupLocationを記述した方法で設定すると、目的の結果が得られます。あるいは、より簡潔に

Window2 w = new Window2(); 
w.Owner = this; // "this" being the parent window 
w.ShowDialog(); 

new Window2 { Owner = this }.ShowDialog(); 
9

さて、レイはこれをすばらしく見せてくれました。簡単に言えば、彼が何を言いたいことは、ウィンドウの位置決めが行われた後、あなたはHeight & Width(ともActualHeight & ActualWidth)をリセットごLoadedイベントであなたのコントロールの内容を設定していること、です。この問題を解決するには

、次の2つの選択肢があります:

    Ownerに応じて、あなたの Windowの位置を再計算するための簡単な方法を追加し、コンストラクタにあなたのコンテンツ値の設定コードを移動し、または、
  1. Loadedイベントの最後にこのメソッドを呼び出します。

...

private void CenterOwner() 
{ 
    if (Owner != null) 
    { 
     double top = Owner.Top + ((Owner.Height - this.ActualHeight)/2); 
     double left = Owner.Left + ((Owner.Width - this.ActualWidth)/2); 

     this.Top = top < 0 ? 0 : top; 
     this.Left = left < 0 ? 0 : left; 
    } 
} 
2

バインドされた動的コンテンツは、ほとんどがGUI直接描画されることがありますが、GUIディスパッチされることがあります。タイマーおよび他のスレッドは、(MVVM)プロパティ変更イベントを開始できます。 WPF Dispacherキューの優先順位を設定するため、近い時間にレンダリングが行われますが、ガーベージ処理は行われません。 レンダリングが終了したら、WPFは処理の順序について何も言えません。つまり、WPFはStartPositionを計算する理想的な時間にはなりません。

WPF-queueがemtpyであることを待つのは難しいことです。 WPFはあなたのコードを処理する時間があることを確信しています。つまり、WindowのShowDialog呼び出しを遅らせることになります。

MVVMやその他のダイナミックスの変更に対して動的コンテンツの変更を実行するには、常にGUIメインスレッドにが必要です。 マルチディスプレイをサポートするために、位置を手動で計算しないでください。非常に複雑です。 WPFがすべての操作を完了したときに、このコードを試してウィンドウを開くと、ウィンドウのみが開きます

 win.Dispatcher.Invoke(new Action(() => win.ShowDialog()), DispatcherPriority.ApplicationIdle); 
関連する問題