【问题标题】:wpf center child window not working with sizetocontentwpf中心子窗口不适用于sizetocontent
【发布时间】:2010-12-16 21:43:27
【问题描述】:

如果我将SizeToContent 设置为WidthAndHeight,则WindowStartupLocation="CenterOwner" 无法正常工作。而不是新窗口的中心位于其父窗口的中心,它看起来更像是子窗口的左上角位于父窗口的中心。 如果我删除 SizeToContent 则一切正常。 怎么了?

【问题讨论】:

    标签: wpf sizetocontent


    【解决方案1】:

    嗯,雷把这件事做得很出色。简单来说,他想说的是,您在Loaded 事件中设置控件的内容,这会在之后重置HeightWidth(以及ActualHeightActualWidth)窗口的定位就完成了。

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

    1. 将您的内容值设置代码移至构造函数,或者,
    2. 添加一个简单的方法来根据Owner 重新计算Window 的位置,并在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】:

      当一个窗口被显示时,它被测量,然后WindowStartupLocation 使用测量过程计算的窗口的ActualWidthActualHeight 进行处理。

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

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

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

      基本上,在调用Show() 时,您需要查找可能导致窗口内容小于正常值的任何内容,然后修复它。

      【讨论】:

      • 谢谢,我实际上是在 Show() 之后加载内容。愚蠢的错误,现在可以正常工作了:)
      【解决方案3】:

      绑定的动态内容大多直接通过 GUI 呈现,但有时通过 GUI 调度。计时器和其他线程可以启动 (MVVM) 属性更改事件。可以肯定的是,渲染是在很短的时间内完成的,但不是保证的,因为定位 WPF 调度程序队列的优先级。 所以,你不能说渲染什么时候完成,WPF也不能说处理的顺序——所以WPF现在不能计算StartPosition的理想时间。

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

      所以给 GUI 主线程它需要的所有时间,以执行 MVVM 的动态内容更改或其他动态更改。 不要尝试手动计算位置,非常复杂,支持多显示。 试试这个代码打开窗口,它只打开窗口,当WPF完成所有操作

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

      【讨论】:

        【解决方案4】:

        你的问题有点模棱两可。您在哪个窗口(“父”或“子”)上设置 SizeToContent 和 WindowStartupLocation?

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

        我能想到的你可能忘记的唯一一件事就是告诉子窗口它的所有者是谁:

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

        或者,更简洁:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-04-21
          • 1970-01-01
          • 2012-02-24
          • 1970-01-01
          • 2011-01-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多