为什么WindowStartupLocation = CenterScreen将我的窗口放在除屏幕中心之外的某个位置?

时间:2009-07-26 21:49:54

标签: wpf xaml

这是窗口声明:

<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">

这是样式声明:

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

讨论:

屏幕为1280 X 1024.窗口大小(由InitialWindowWidth,InitialWindowHeight绑定决定)为800 X 600。

当窗口打开时,它显示188,141(左,上)。这基本上应该是“西北”。如果我计算真正的居中值,它应该是240,212(左,上)。

一个线索?

总是第一个窗口出现问题。如果我打开同一窗口的第二个实例,它将显示在正确的位置。

另一条线索?

如果我在打开第一个实例之前创建了两个实例,那么第二个窗口实例将显示在正确的位置。

因此...

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

...抵消win1和win2

但是...

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

...抵消win1,但显示win2死亡中心。

所以我的问题是:

这里发生了什么???


修改

又一条线索。如果我添加......

Width="800"
Height="600"

...到我的Window声明,偏移问题消失了。但这不是我的解决方案,因为我需要将窗口大小作为首选项存储在设置文件中。这就是我在我的Style中有数据绑定的原因。 (请注意,Width和Height的数据绑定工作正常 - 所有窗口都显示为正确的大小。)


编辑#2:

我在调试模式下检查了宽度和高度,得出了这个有趣的结论:

如果我创建了多个窗口实例但没有打开任何窗口,则所有窗口实例的“宽度”和“高度”属性都是“NaN”。

如果我然后只打开一个实例,所有窗口实例的宽度和高度属性都是突然有效的数字,而不仅仅是窗口的宽度和高度我打开了。

这告诉我WPF推迟数据绑定,直到在第一个窗口调用Show()。

- &gt; 现在问题变成了:我可以强制WPF在显示第一个窗口之前进行数据绑定吗?


编辑#3:

我刚刚向Microsoft提交了有关此问题的错误报告。这是链接:

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

编辑#4:解决方法

目前还没有真正的解决方案,但我刚刚确认您可以使用虚拟窗口解决问题。请按照以下步骤操作:

  1. 创建一个名为“BlankWindow”的新XPF窗口(参见下面的XAML)。
  2. 创建一个BlankWindow实例以及您希望在屏幕上居中的窗口(FirstWindow)。
  3. 执行以下代码序列:
  4. ...

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

    我的虚拟窗口的XAML只不过是:

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

    在“FirstWindow”打开之前我没有看到明显的闪烁,所以我认为这是一个足够好的解决方法,直到MS开始修复bug。

4 个答案:

答案 0 :(得分:4)

你的WidthHeight绑定会妨碍你吗?如果您根本没有设置WidthHeight,窗口是否显示在正确的位置?如果是这样,那个位置是否与上面设置的绑定相同?

如果一切正确,那么听起来WPF在从绑定中获取WidthHeight的值之前计算窗口的位置。我不确定解决这个问题的好方法 - 可能首先手动设置WidthHeight(在XAML或构造函数中),然后在显示绑定后设置它?

答案 1 :(得分:1)

另一种解决方法......为绑定添加一个后备值。

Width="{Binding Width, FallbackValue=500}" Height="{Binding Height, FallbackValue=500}"

答案 2 :(得分:0)

我的示例中没有看到任何对Margins的引用。但是,当Visual Studio在设计器中拖动对象的一侧后更改项目的边距(当它们在网格中时)时,我常常感到沮丧(我认为它会改变它的宽度,而不是它的边距)。并且,有奇怪的边距会导致意外的放置问题。

答案 3 :(得分:0)

这是相当古老的帖子,但由于我找不到任何合适的解决方案,我还有另一个解决办法: 您可以手动计算对话框的位置(http://social.msdn.microsoft.com/Forums/eu/wpf/thread/054800c3-56dc-4700-a2fb-d2b79fc9ef9a)。

不是很优雅,但它有效:

public class Controller
{
     private Double CalcCoordinate(Double parentCoordinate, Double parentSize, Double thisSize)
     {
          return parentCoordinate + (parentSize - thisSize) / 2;
     }
     public Controller(Double width, Double height, Window owner)
     {
          Width = width;
          Height = height;
          Left = CalcCoordinate(owner.Left, owner.Width, Width);
          Top = CalcCoordinate(owner.Top, owner.Height, Height);
     }

public Double Width { get; set; }
public Double Height { get; set; }
public Double Left { get; set; }
public Double Top { get; set; }

}

然后,只需将窗口的位置和大小绑定到这些属性,并且不要忘记将WindowStartupLocation更改为Manual。

出于某种原因,我只是没有得到,顶部/左侧必须以双向模式绑定,没有它我无法正常工作。