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?
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:
Window2 w = new Window2();
w.Owner = this; // "this" being the parent window
w.ShowDialog();
Or, more succinctly:
new Window2 { Owner = this }.ShowDialog();
When a window is shown, it is measured, then WindowStartupLocation
is processed using the ActualWidth
and ActualHeight
of the window computed by the measure process.
The behavior you describe tells me ActualWidth
and ActualHeight
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 the Show()
is called, the window has not been Loaded
yet so it has no data. Later when the Loaded
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.
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 the Height
& Width
(and also the ActualHeight
& ActualWidth
) after the positioning of the window is done.
To fix this, you have two alternatives:
- Move your content value setting code to the constructor, or,
- Add a simple method to recalculate the position of your
Window
according to theOwner
and call this method at the end of yourLoaded
event, like this:
...
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;
}
}
Thanks for your answers. I am posting instead of leaving comment because i need to post code. What i am doing is that i am creating a new window upon an event triggering such as a button click. So my parent window has been set along with its datacontext.
windowProfile = new WindowProfile();
windowProfile.Owner = windowMain;
windowProfile.Opacity = 0;
windowProfile.Show();
//globalFuncs.CenterOwner(ref windowMain, ref windowProfile);
// doing some stuff here
globalFuncs.FadeInElement(windowProfile, 0.5,
globalFuncs.windowFinalOpacity, true);
the reason i am using opacity = 0 is because i am fading in my custom window. Any datacontext of the childwindow is set in its constructor after the initializecomponents is called. If i remove sizetocontent from my child window's xaml then it works fine. If i use this, then it doesnt. Does that make any more sense now?