wpf中心子窗口不与sizetocontent一起工作

时间:2009-11-16 00:37:09

标签: wpf sizetocontent

如果我将SizeToContent设置为WidthAndHeight,则WindowStartupLocation="CenterOwner"无效。而不是新窗口的中心位于其父所有者的中心,它看起来更像是子窗口的左上角位于父窗口的中心。 如果我删除SizeToContent,那么一切正常。 有什么问题?

4 个答案:

答案 0 :(得分:9)

嗯,雷已经把它放得很好。简单来说,他想说的是,您要在Loaded事件中设置控件的内容,这会重置Height&完成窗口定位后Width(以及ActualHeight& ActualWidth)。

要解决此问题,您有两种选择:

  1. 将内容值设置代码移至构造函数,或
  2. 添加一种简单方法,根据Window重新计算Owner的位置,并在Loaded事件结束时调用此方法,如下所示:
  3. ...

    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;
        }
    }
    

答案 1 :(得分:6)

当显示窗口时,会对其进行测量,然后使用度量过程计算的窗口的WindowStartupLocationActualWidth处理ActualHeight

您描述的行为告诉我{(1}}和ActualWidth在Show()或ShowDialog()调用时被测量为零或相对较小,并且稍后才设置为非零值。

例如,如果窗口的内容是使用仅在ActualHeight事件上设置的DataContext构建的,则会发生这种情况。调用Loaded时,窗口尚未Show(),因此它没有数据。稍后当Loaded事件触发时,它会设置DataContext,窗口会更新其内容,但定位已经发生。

还有许多其他方案,例如使用Dispatcher.BeginInvoke调用填充的内容,或来自单独的线程,或延迟或异步的绑定。

基本上,您需要查找任何可能导致窗口内容在调用Loaded时小于正常值的内容,并进行修复。

答案 2 :(得分:3)

Binded动态内容主要是直接呈现Gui,但有时会进行GUI调度。计时器和其他线程可以启动(MVVM)属性更改事件。可以肯定的是,渲染是在近时间内完成的,但没有保证,因为定位了WPF Dispacher队列的优先级。 所以,你不能说渲染完成后,WPF无法说出处理顺序 - 所以WPF现在不能是计算StartPosition的理想时间。

一个技巧是,等待,WPF队列是空的。那么你确定,WPF有时间处理你的代码。这意味着,您延迟了Window的ShowDialog调用。

因此,在需要的时候给予GUI-Main Thread ,以便为MVVM或其他动态变化执行动态内容更改。 不要手动计算位置,它非常复杂,支持多显示器。 尝试使用此代码打开窗口,当 WPF完成所有操作时,只打开窗口。

        win.Dispatcher.Invoke(new Action(() => win.ShowDialog()), DispatcherPriority.ApplicationIdle);

答案 3 :(得分:1)

你的问题有点含糊不清。在哪个窗口(“父”或“子”)上设置SizeToContent和WindowStartupLocation?

如果我在项目中创建第二个窗口并按照您描述的方式设置其SizeToContent和WindowStartupLocation,我会得到所需的结果。

我唯一可以想到的是你可能会忘记的是实际告诉孩子窗口其所有者是谁:

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

或者,更简洁:

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