【问题标题】:WindowStartupLocation CenterOwner is only working in Visual StudioWindowStartupLocation CenterOwner 仅在 Visual Studio 中工作
【发布时间】:2019-05-15 08:53:50
【问题描述】:

我刚刚在我的 WPF 应用程序中偶然发现了一些奇怪的行为。

我尝试确保某些窗口将与其“父窗口”显示在同一屏幕上。

为此,我使用了 Window-Property WindowStartupLocation = CenterOwner,它在直接从 Visual Studio 运行时按预期运行。

奇怪的是,当我运行完全相同的 .exe (...\Project\bin\Debug\Project.exe)“手动”,“子窗口”无论我是否移动了“父窗口”,总是在我的主屏幕上启动。

因此,当我将“父窗口”移动到第二个屏幕并打开“子窗口”时,它仍将显示在我的主屏幕上,而不是像预期的那样显示在我的第二个屏幕上。

所以我的问题是,如果我运行 .exe,我会得到不同的行为 “手动”或直接从 Visual Studio。

我使用的扩展方法:

public static class ExtensionMethods {
//I created these Extensions, to easily show Windows on the same screen, as a give Window.

    public static bool? ShowDialog(this Window child, Window owner) {
        child.WindowStartupLocation = WindowStartupLocation.CenterOwner;
        child.Owner = owner;
        return child.ShowDialog();
    }

    public static void Show(this Window child, Window owner) {
        child.WindowStartupLocation = WindowStartupLocation.CenterOwner;
        child.Owner = owner;
        child.Show();
    }
}

我如何打开一个新的“子窗口”

public void test(Window pw) {
    ChildWindow cw = new ChildWindow();
    cw.ShowDialog(pw); //Edited typo from "cw.ShowDialog(w);"
}



编辑:

我刚刚创建了一个新项目,其中只有两个 Windows 和扩展方法,以便在干净的环境中试用。

在这个过程中,我发现只有在第二个窗口最大化时才会出现问题。无论是在 xaml 中设置 WindowState = Maximized 时,还是通过子窗口构造函数上的代码设置。

不过,直接从 Visual Studio 中,行为与预期的一样,但在直接运行 .exe 时则不然。

我的“新鲜”项目的整个代码:

主窗口 XAML:

<Window x:Class="WpfApplication3.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Button Content="Open Child" Click="btn"/>
    </Grid>
</Window>

主窗口cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApplication3 {
    /// <summary>
    /// Interaktionslogik für MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window {
        public MainWindow() {
            InitializeComponent();
        }

        public void btn(object sender, RoutedEventArgs e) {
            test(this);
        }

        public void test(Window pw) {
            ChildWindow cw = new ChildWindow();
            cw.ShowDialog(pw);
        }
    }

    public static class ExtensionMethods {
        //I created these Extensions, to easily show Windows on the same screen, as a give Window.

        public static bool? ShowDialog(this Window child, Window owner) {
            child.WindowStartupLocation = WindowStartupLocation.CenterOwner;
            child.Owner = owner;
            return child.ShowDialog();
        }

        public static void Show(this Window child, Window owner) {
            child.WindowStartupLocation = WindowStartupLocation.CenterOwner;
            child.Owner = owner;
            child.Show();
        }
    }
}

子窗口 XAML:

<Window x:Class="WpfApplication3.ChildWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ChildWindow" Height="300" Width="300"
        WindowState="Maximized">
    <Grid>
        <TextBlock Text="CHILD"/>
    </Grid>
</Window>

子窗口cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace WpfApplication3 {
    /// <summary>
    /// Interaktionslogik für ChildWindow.xaml
    /// </summary>
    public partial class ChildWindow : Window {
        public ChildWindow() {
            InitializeComponent();
        }
    }
}

【问题讨论】:

  • 您确定您运行的 .exe 版本正确吗?
  • 是的,我运行的是正确的版本,因为它是唯一的版本^^
  • 如果它是“唯一版本”,您只编译了一次应用程序。每次成功构建都会生成一个新的 .exe。话虽如此,恐怕我无法重现您的问题。
  • 好的,找到了新的信息,既然你告诉我,你不能重现问题,我创建了一个新的项目,只写了受影响的代码。在此过程中,我发现了一条新信息,更新了我的答案。
  • 可以保证没有错别字,贴出我示例项目的全部代码

标签: c# wpf


【解决方案1】:

虽然我仍然不明白为什么会发生这种行为,但我仍然找到了解决方法。

这个问题似乎与最大化的“子窗口”蜜蜂有关。当 WindowState 没有改变时,无论是在 VS 中还是在直接执行时,行为都符合预期。

我的解决方法是,在加载窗口后最大化窗口,因为它已经在正确的屏幕上。

子窗口构造函数中的示例代码:

public ChildWindow() {
    InitializeComponent();

    this.Loaded += delegate(object ds, RoutedEventArgs de) {
        ((Window)ds).WindowState = System.Windows.WindowState.Maximized;
    };
}

如果有人偶然发现这个问题并且有更多关于为什么会出现这个问题的信息,请随时分享。

对我来说,这是一个小不便,但它正在工作,所以我现在要这样做。



编辑:

也为了大家感兴趣,为了减少不便,我稍微改变了我的 ExtensionMethod:

public static bool? ShowDialog(this Window child, Window owner) {
    child.WindowStartupLocation = WindowStartupLocation.CenterOwner;
    child.Owner = owner;

    //Detects, if the Window should be Maximized. If so set the State to
    //Normal instead and add an Eventhandler to Maximize the Window after beeing loaded.
    if (child.WindowState == WindowState.Maximized) {
        child.WindowState = WindowState.Normal;
        child.Loaded += delegate(object ds, RoutedEventArgs de) {
            ((Window)ds).WindowState = System.Windows.WindowState.Maximized;
        };
    }

    return child.ShowDialog();
}

这样,您可以像往常一样在 XMAL 中设置 WindowState,而无需自己在加载的事件中显式设置。

【讨论】:

    猜你喜欢
    • 2012-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-02
    • 2013-08-29
    • 1970-01-01
    相关资源
    最近更新 更多