Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does WindowStartupLocation = CenterScreen place my window somewhere other than the center of the screen?

Tags:

wpf

xaml

Here's the Window declaration:

<Window
    x:Class="Pse.ExperimentBase.SplashWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Style="{StaticResource _windowStyle}"
    WindowStartupLocation="CenterScreen"
    WindowStyle="None">

Here's the Style declaration:

<Style
    x:Key="_windowStyle"
    TargetType="Window">
    <Setter
        Property="Width"
        Value="{Binding Path=InitialWindowWidth}" />
    <Setter
        Property="Height"
        Value="{Binding Path=InitialWindowHeight}" />
    <Setter
        Property="Icon"
        Value="Resources/MyIcon.ico" />
    <Setter
        Property="Background"
        Value="{StaticResource _fadedOrangeBrush}" />
    <Setter
        Property="FontSize"
        Value="11" />
</Style>

Discussion:

The screen is 1280 X 1024. The window size (determined by the InitialWindowWidth, InitialWindowHeight bindings) is 800 X 600.

When the Window opens, it appears 188, 141 (left, top). This is basically "northwest" of where it should be. If I calculate the true centered values, it should be 240, 212 (left, top).

A clue?

It's always the first window that has the problem. If I open a second instance of the same window, it will show up in the correct location.

Another clue?

The second window instance will only show up in the correct location if I create both instances before opening the first one.

So...

Window win1 = windowFactory.CreateSplashWindow();
win1.Show();
Window win2 = windowFactory.CreateSplashWindow();
win2.Show();
win1.Hide();

...offsets both win1 and win2

But...

Window win1 = windowFactory.CreateSplashWindow();
Window win2 = windowFactory.CreateSplashWindow();
win1.Show();
win2.Show();
win1.Hide();

...offsets win1 but shows win2 dead center.

So my question is:

What is going on here???


EDIT:

Yet another clue. If I add...

Width="800"
Height="600"

...to my Window declaration, the offset problem disappears. This isn't a solution for me, though, because I need the window size to be a preference stored in a settings file. That's why I have the data binding in my Style. (And note, the data binding for the Width and Height works fine--all windows show up as the correct size).


EDIT #2:

I did checking of widths and heights while in debug mode and came to this interesting conclusion:

If I create multiple window instances but don't open any windows, the Width and Height properties of all window instances are "NaN".

If I then open just one of the instances, the width and height properties of all window instance are suddenly valid numbers, not just the width and height of the window I opened.

This tells me that WPF defers data-binding until Show() is called on the first window.

--> So now the question becomes: Can I force WPF to do the data-binding before I show the first window?


Edit #3:

I just submitted submitted a bug report on this issue to Microsoft. Here is the link:

https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=477598

Edit #4: A Workaround

No real resolution on this yet, but I just confirmed that you can work around the problem using a dummy window. Follow these steps:

  1. Create a new XPF Window called "BlankWindow" (see XAML below).
  2. Create an instance of BlankWindow plus the window you'd like to be centered on the screen (FirstWindow).
  3. Execute the following code sequence:

...

BlankWindow.Show()
FirstWindow.Show()
BlankWindow.Hide()

The XAML for my dummy window is nothing more than this:

<Window
    x:Class="Pse.ExperimentBase.Windows.BlankWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="BlankWindow"
    Height="0"
    Width="0"
    WindowStyle="None">
    <Grid></Grid>
</Window>

I see no noticeable flicker before "FirstWindow" opens, so I consider it a good enough workaround until MS get around to fixing the bug.

like image 689
devuxer Avatar asked Jul 26 '09 21:07

devuxer


2 Answers

Could your Width and Height bindings be getting in the way? If you don't set the Width and Height at all, does the window appear in the correct location? If so, is that the same location as when you have the bindings set as above?

If all that is true, then it sounds like WPF is computing the location of the window prior to getting the value of Width and Height from your bindings. I'm not sure of a good way to get around this - maybe set Width and Height manually at first (either in XAML or the constructor), then set up the bindings once it has been displayed?

like image 186
Andy Avatar answered Nov 17 '22 00:11

Andy


Another workaround...add a fallback value to the bindings.

Width="{Binding Width, FallbackValue=500}" Height="{Binding Height, FallbackValue=500}"
like image 39
Spivonious Avatar answered Nov 17 '22 00:11

Spivonious