WPF: Як встановити діалогове положення, яке відображатиметься в центрі програми?


84

Як встановити позицію діалогу, яка з’явилася, .ShowDialog();щоб показати в центрі основного Windows.

Це спосіб, яким я намагаюся встановити позицію.

private void Window_Loaded(object sender, RoutedEventArgs e)
{        
    PresentationSource source = PresentationSource.FromVisual(this);
    if (source != null)
    {
        Left = ??
        Top = ??
    }
}

Відповіді:


35

Ви можете спробувати затримати MainWindow у події Loaded, як це

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    Application curApp = Application.Current;
    Window mainWindow = curApp.MainWindow;
    this.Left = mainWindow.Left + (mainWindow.Width - this.ActualWidth) / 2;
    this.Top = mainWindow.Top + (mainWindow.Height - this.ActualHeight) / 2;
}

8
Це ставить лівий верхній кут у центрі. Ця відповідь , яка не була прийнята, точніше виконує бажання ОП.
Кріс Шиффауер,

278

У XAML, що належить діалогу:

<Window ... WindowStartupLocation="CenterOwner">

і в C # під час створення діалогового вікна:

MyDlg dlg = new MyDlg();
dlg.Owner = this;

if (dlg.ShowDialog() == true)
{
    ...

17
насправді міг зробити var dlg = new MyDlg { Owner = this };на другому біті.
Джодрелл

6
Якщо ви використовуєте шаблон MVVM, ви можете скористатися цим, щоб знайти власника:dlg.Owner = Application.Current.MainWindow;
Якоб Буськ Серенсен

55

Я думаю, що простіше використовувати розмітку xaml

<Window WindowStartupLocation="CenterOwner">

Ні, я не можу цим скористатися, оскільки батько не є головним вікном
Prince OfThief

6
Ви можете зробити будь-яке вікно власником, встановивши Window.Owner.
Богдан

10
ммм CenterParentабо CenterOwner? Я бачу лише CenterOwnerв Intellisense
Brock Hensley

@dirt це може залежати від того, яку версію WPF ви використовуєте.
BrainSlugs83,

CenterOwner та CenterParent різняться між WPF та WinForms, відповідно
F8ER

21

Просто в коді позаду.

public partial class CenteredWindow:Window
{
    public CenteredWindow()
    {
        InitializeComponent();

        WindowStartupLocation = WindowStartupLocation.CenterOwner;
        Owner = Application.Current.MainWindow;
    }
}

19

Я думаю, що відповіді кожного на це питання є частинами того, якою має бути відповідь. Я просто складу їх, що, на мою думку, є найпростішим та елегантним підходом до цієї проблеми.

Спочатку налаштуйте там, де потрібно розмістити вікно. Ось це власник.

<Window WindowStartupLocation="CenterOwner">

Перш ніж відкривати вікно, нам потрібно надати йому власника, а з іншого повідомлення ми можемо отримати доступ до MainWindow за допомогою статичного геттера для MainWindow поточної програми.

        Window window = new Window();
        window.Owner = Application.Current.MainWindow;
        window.Show();

Це воно.


1
Батьківський центр не існує, у цьому випадку WindowStartupLocation має бути CenterOwner.
Умпа

1
Дякую що дали мені знати. Не знаю, чому я ставлю CenterParent. Це було змінено.
Alex Ehlert

1
Я не знаю, чому це рішення не прийняте, це те, що потрібно, щоб уникнути головних болів обчислень, тоді як WPF має це нестандартне рішення ...
cdie

2
Це найкраще рішення.
Бейондо,

1
Я закінчив робити саме це, перш ніж перейти до цієї відповіді. +1 для наочності!
Алексіс Леклерк,

8

Я знайшов цей найкращий

frmSample fs = new frmSample();
fs.Owner = this; // <-----
fs.WindowStartupLocation = WindowStartupLocation.CenterOwner;
var result = fs.ShowDialog();

5

Якщо ви мало контролюєте вікна, які вам потрібно показати, наступний фрагмент може бути корисним

    public void ShowDialog(Window window)
    {
        Dispatcher.BeginInvoke(
            new Func<bool?>(() =>
            {
                window.Owner = Application.Current.MainWindow;
                window.WindowStartupLocation = WindowStartupLocation.CenterOwner;
                return window.ShowDialog();
            }));
    }

Цікаво, чому це не набрало багато голосів. Для мене так слід робити. Щоб централізувати власника, ви повинні призначити власника, і тоді він працює без злому.
ВПЗ

3

Щоб діалогове вікно WPF розмістилося в центрі батьківської форми Windows Forms, я передав батьківську форму в діалогове вікно, оскільки Application.Current не повернув батьківський форму Windows Form (я припускаю, що це працює, лише якщо батьківська програма WPF).

public partial class DialogView : Window
{
    private readonly System.Windows.Forms.Form _parent;

    public DialogView(System.Windows.Forms.Form parent)
    {
        InitializeComponent();

        _parent = parent;
    }

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        this.Left = _parent.Left + (_parent.Width - this.ActualWidth) / 2;
        this.Top = _parent.Top + (_parent.Height - this.ActualHeight) / 2;
    }
}

встановіть WindowStartupLocation у діалоговому вікні WPF:

<Window WindowStartupLocation="CenterParent">

і спосіб завантаження форми Windows у діалогове вікно WPF такий:

DialogView dlg = new DialogView();
dlg.Owner = this;

if (dlg.ShowDialog() == true)
{
    ...

2

Ви повинні встановити батьківське вікно для свого вікна (Власник), а потім встановити для властивості WindowStartupLocation значення "CenterParent"


2
Правда, у WPF властивість називається "CenterOwner", а не "CenterParent".
бета-версія

2

Я хотів би додати до відповіді Фредріка Хедблада, що якщо розмір MainWindows був змінений або розгорнутий, результат був би неправильним, оскільки mainWindow.Width і mainWindow.Height відображають значення, встановлені в XAML.

Якщо вам потрібні фактичні значення, ви можете використовувати mainWindow.ActualWidth і mainWindow.ActualHeight:

private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        Application curApp = Application.Current;
        Window mainWindow = curApp.MainWindow;
        this.Left = mainWindow.Left + (mainWindow.ActualWidth - this.ActualWidth) / 2;
        this.Top = mainWindow.Top + (mainWindow.ActualHeight - this.ActualHeight) / 2;
    }


0

Цей код працює, якщо ви не хочете використовувати властивість WindowStartupLocation у xaml:

private void CenterWindowOnApplication()
{
    System.Windows.Application curApp = System.Windows.Application.Current;
    Window mainWindow = curApp.MainWindow;
    if (mainWindow.WindowState == WindowState.Maximized)
    {
        // Get the mainWindow's screen:
        var screen = System.Windows.Forms.Screen.FromRectangle(new System.Drawing.Rectangle((int)mainWindow.Left, (int)mainWindow.Top, (int)mainWindow.Width, (int)mainWindow.Height));
        double screenWidth = screen.WorkingArea.Width;
        double screenHeight = screen.WorkingArea.Height;
        double popupwindowWidth = this.Width;
        double popupwindowHeight = this.Height;
        this.Left = (screenWidth / 2) - (popupwindowWidth / 2);
        this.Top = (screenHeight / 2) - (popupwindowHeight / 2);
    }
    else
    {
        this.Left = mainWindow.Left + ((mainWindow.ActualWidth - this.ActualWidth) / 2;
        this.Top = mainWindow.Top + ((mainWindow.ActualHeight - this.ActualHeight) / 2);
    }
}

Я використовую "screen.WorkingArea", оскільки панель завдань зменшує mainWindow. Якщо ви хочете розмістити вікно посередині екрана, ви можете замість нього використовувати "screen.Bounds".


0

Для дочірнього вікна встановіть XAML

WindowStartupLocation="CenterOwner"

Щоб викликати своє дочірнє вікно як діалогове вікно та центр батьківського, викличте його з батьківського вікна, наприклад

private void ConfigButton_OnClick(object sender, RoutedEventArgs e)
{
    var window = new ConfigurationWindow
    {
        Owner = this
    };
    window.ShowDialog();
}

0

Задля документації я додаю тут приклад того, як я досяг чогось подібного. Мені потрібно було спливаюче вікно, яке охоплювало всю батьківську область вмісту Вікна (за винятком рядка заголовка), але просто центрирувати діалогове вікно та розтягувати його вміст не працювало, оскільки діалогове вікно завжди було трохи зміщене знизу.

Примітка щодо взаємодії з користувачем: Неприємно не перетягувати / закривати батьківське вікно, коли відображається діалогове вікно без полів, тому я б подумав про його використання. Я також вирішив не робити цього після публікації цієї відповіді, але залишу це для інших.

Після деяких пошуків і тестування мені нарешті вдалося зробити це так:

var dialog = new DialogWindow
{
    //this = MainWindow
    Owner = this
};

dialog.WindowStartupLocation = WindowStartupLocation.Manual;
dialog.WindowStyle = WindowStyle.None;
dialog.ShowInTaskbar = false;
dialog.ResizeMode = ResizeMode.NoResize;
dialog.AllowsTransparency = true;

var ownerContent = (FrameworkElement) Content;
dialog.MaxWidth = ownerContent.ActualWidth;
dialog.Width = ownerContent.ActualWidth;
dialog.MaxHeight = ownerContent.ActualHeight;
dialog.Height = ownerContent.ActualHeight;    

var contentPoints = ownerContent.PointToScreen(new Point(0, 0));
dialog.Left = contentPoints.X;
dialog.Top = contentPoints.Y;

dialog.ShowDialog();

Це DialogWindow- Вікно, а його власник встановлений як головне Вікно програми. WindowStartupLocationПовинен бути встановленийManual для ручного позиціонування до роботи.

Результат:

Не відображається діалогове вікно

Відображення модального діалогу

Не знаю, чи є простіший спосіб зробити це, але, здавалося б, ніщо інше не спрацювало для мене.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.