WPF: Как настроить положение диалогового окна в центре приложения?

86

Как установить положение диалогового .ShowDialog();окна, которое появилось из, так, чтобы оно отображалось в центре главного окна.

Так я пытаюсь установить позицию.

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
Это поместит верхний левый угол в центр. Этот ответ , который не был принят, более точно исполняет желание ОП.
Крис Шиффхауэр
280

В XAML, принадлежащем Dialog:

<Window ... WindowStartupLocation="CenterOwner">

и в C # при создании экземпляра Dialog:

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

if (dlg.ShowDialog() == true)
{
    ...
Chessweb
источник
17
действительно мог бы сделать var dlg = new MyDlg { Owner = this };на втором бите.
Jodrell
6
Если вы используете шаблон MVVM, вы можете использовать его, чтобы найти владельца:dlg.Owner = Application.Current.MainWindow;
Якоб Буск Соренсен,
56

Я думаю, что проще использовать разметку xaml

<Window WindowStartupLocation="CenterOwner">
Наименьший
источник
Нет, я не могу использовать это, потому что родитель не является
основным окном
6
Вы можете сделать любое окно владельцем, установив Window.Owner.
Богдан
10
ммм CenterParentили CenterOwner? Я вижу только CenterOwnerв Intellisense
Брок Хенсли
@dirt это может зависеть от того, какую версию WPF вы используете.
BrainSlugs83
CenterOwner и CenterParent отличаются между WPF и WinForms соответственно
F8ER,
22

Просто в коде позади.

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.
Umpa
1
Спасибо, что дал мне знать. Понятия не имею, зачем я поставил CenterParent. Это было изменено.
Alex Ehlert
1
Я не знаю, почему это решение не принято, это то, что нужно, чтобы избежать головной боли с вычислениями, в то время как WPF имеет это как готовое решение ...
cdie
2
Это лучшее решение.
Beyondo
1
Я закончил тем, что сделал именно это, прежде чем прокрутил до этого ответа. +1 за наглядность!
Alexis Leclerc
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 Form загружает диалоговое окно 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();
}
небо91
источник
0

Для документации я добавлю здесь пример того, как я добился чего-то подобного. Что мне было нужно, так это всплывающее окно, охватывающее всю область содержимого родительского окна (за исключением строки заголовка), но простое центрирование диалогового окна и растягивание его содержимого не работало, потому что диалоговое окно всегда было немного смещено снизу.

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

После некоторого поиска в Google и тестирования мне наконец удалось сделать это вот так:

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 работы ручного позиционирования .

Результат:

Диалог не отображается

Отображение модального диалога

Не знаю, есть ли более простой способ сделать это, но, похоже, у меня ничего не работало.

Шахин Дохан
источник