WPF 中心子窗口无法使用 sizetocontent
如果我将 SizeToContent
设置为 WidthAndHeight
,则 WindowStartupLocation="CenterOwner"
无法正常工作。新窗口的中心不是位于其父窗口的中心,而是看起来更像是子窗口的左上角位于父窗口的中心。 如果我删除 SizeToContent
那么一切都可以。 怎么了?
If i set SizeToContent
to WidthAndHeight
, then WindowStartupLocation="CenterOwner"
does not work properly. Instead of the center of the new window to be at the center of its parent owner, it looks more like the top left hand corner of the child window to be at the center of the parent.
If i remove SizeToContent
then all is ok.
What is wrong?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
好吧,雷把这一点说得非常出色。简单来说,他想说的是,您在
Loaded
事件中设置控件的内容,该事件会重置Height
和高度。窗口定位完成后的Width
(以及ActualHeight
和ActualWidth
)。要解决此问题,您有两种选择:
Owner
重新计算Window
的位置并在Loaded
事件结束时调用此方法,如下所示:...
Well, Ray has put this up brilliantly. In simple terms, what he wants to say is, that you are setting the content of your controls in your
Loaded
event, which resets theHeight
&Width
(and also theActualHeight
&ActualWidth
) after the positioning of the window is done.To fix this, you have two alternatives:
Window
according to theOwner
and call this method at the end of yourLoaded
event, like this:...
当显示窗口时,对其进行测量,然后使用测量过程计算出的窗口的
ActualWidth
和ActualHeight
来处理WindowStartupLocation
。您描述的行为告诉我
ActualWidth
和ActualHeight
在 Show() 或 ShowDialog() 调用时被测量为零或相对较小,然后才设置为非零值。例如,如果窗口的内容是使用仅在
Loaded
事件上设置的 DataContext 构建的,则可能会发生这种情况。当调用Show()
时,窗口尚未Loaded
,因此它没有数据。稍后,当Loaded
事件触发时,它会设置 DataContext 并且窗口会更新其内容,但定位已经发生。还有许多其他场景,例如使用 Dispatcher.BeginInvoke 调用填充的内容,或者来自单独线程的内容,或者延迟或异步的绑定。
基本上,您需要查找任何可能导致调用
Show()
时窗口内容小于正常内容的因素,并修复它。When a window is shown, it is measured, then
WindowStartupLocation
is processed using theActualWidth
andActualHeight
of the window computed by the measure process.The behavior you describe tells me
ActualWidth
andActualHeight
are measured to be either zero or relatively small at the time of the Show() or ShowDialog() call and only later set to nonzero values.This can happen if, for example, the content of the window is built using a DataContext that is only set on a
Loaded
event. When theShow()
is called, the window has not beenLoaded
yet so it has no data. Later when theLoaded
event fires it sets DataContext and the window updates its content but the positioning has already occured.There are many other scenarios, for example contents filled using a Dispatcher.BeginInvoke call, or from a separate thread, or bindings that are delayed or asynchronous.
Basically you need to look for anything that could cause the content of your window to be smaller than normal at the moment
Show()
is called, and fix it.绑定的动态内容大多直接通过 GUI 呈现,但有时通过 GUI 调度。计时器和其他线程可以发起(MVVM)属性更改事件。可以肯定的是,渲染会在很短的时间内完成,但不能保证,因为位置是 WPF 调度程序队列的优先级。
因此,您无法说出渲染何时完成,并且 WPF 无法说出有关处理顺序的信息 - 因此 WPF 现在无法计算 StartPosition 的理想时间。
一个技巧是等待 WPF 队列为空。那么您就可以确定 WPF 有时间处理您的代码。这意味着,您延迟了 Window 的 ShowDialog 调用。
因此,请为 GUI 主线程提供所需的所有时间,以执行 MVVM 的动态内容更改或其他动态更改。
不要尝试手动计算位置,它非常复杂,要支持多显示器。
尝试使用此代码打开窗口,当WPF完成所有操作时,它仅打开窗口。
Binded dynamic content is mostly rendered Gui-directly but sometimes GUI-dispatched. Timer and other threads can initiate (MVVM) property change events. It is sure, that the rendering is done in near time, but not garanted, because position an priority of the WPF Dispacher queue.
So, you can not say when rendering is finished, and WPF cannot say something about the order of processing- so WPF cannot now the ideal time to calculate the StartPosition.
A trick is, to wait, that the WPF-queue is emtpy. Then you are sure that, WPF has time to process your code. That means, you delay the ShowDialog call for the Window.
So give the GUI-Main Thread all the time it needs, to perform the dynamic content changes for MVVM or other dynamics changes.
Do not try to calculate the position manually, it is very complex, to support multi displays.
Try this code to open the window, it opens the Window only, when WPF finished all operations.
你的问题有点模棱两可。您在哪个窗口(“父”或“子”)上设置 SizeToContent 和 WindowStartupLocation?
如果我在项目中创建第二个窗口并按照您描述的方式设置其 SizeToContent 和 WindowStartupLocation,我会得到所需的结果。
我能想到的唯一你可能忘记的事情就是实际告诉子窗口它的所有者是谁:
或者,更简洁地说:
Your question is a bit ambiguous. On which window (the "parent" or the "child") are you setting SizeToContent and WindowStartupLocation?
If I create a second window in my project and set its SizeToContent and WindowStartupLocation the way you describe, I get the desired results.
The only thing I can think of that you may be forgetting is to actually tell the child window who its Owner is:
Or, more succinctly: