WindowStartupLocation CenterOwner работает только в Visual Studio - PullRequest
1 голос
/ 15 мая 2019

Я только что наткнулся на какое-то странное поведение в своем 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 и методы расширения, чтобы попробовать его в чистой среде.

В этом процессе я обнаружил, чтопроблема возникает только тогда, когда второе окно развернуто.И при установке WindowState = Maximized в xaml, или с помощью кода в конструкторе дочернего окна.

Тем не менее, непосредственно из Visual Studio, поведение такое же, как и ожидалось, но не при непосредственном запуске .exe.

Весь код моего "свежего" проекта:

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

MainWindow 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();
        }
    }
}

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

ChildWindow 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();
        }
    }
}

1 Ответ

1 голос
/ 15 мая 2019

То есть я до сих пор не понимаю, почему происходит такое поведение, я все еще нашел обходной путь.

Проблема, похоже, связана с тем, что «Детское окно» максимизируется. Когда WindowState не изменяется, как в VS, так и при непосредственном выполнении, поведение соответствует ожидаемому.

Моя работа заключается в том, чтобы максимизировать окно после загрузки окна, потому что тогда оно находится на правильном экране.

Пример кода в конструкторе дочернего окна:

public ChildWindow() {
    InitializeComponent();

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

Тем не менее, если кто-то наткнется на этот вопрос и получит дополнительную информацию о причинах возникновения этой проблемы, не стесняйтесь поделиться.

Что касается меня, то это незначительное неудобство, но оно работает, поэтому я собираюсь пойти на это сейчас.



Edit:

Также для всех, кто заинтересован, для еще меньшего неудобства я немного изменил свой 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();
}

Таким образом, вы можете установить WindowState в XMAL, как обычно, и вам не нужно явно устанавливать загруженное событие самостоятельно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...