WPF: Wie kann eine Dialogposition festgelegt werden, die in der Mitte der Anwendung angezeigt wird?


80

So legen Sie die Position von Dialog fest, von der aus .ShowDialog();sie in der Mitte des Hauptfensters angezeigt wird.

Auf diese Weise versuche ich, die Position festzulegen.

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

Antworten:


33

Sie können versuchen, das MainWindow im Loaded-Ereignis wie folgt zu erreichen

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
Dadurch wird die obere linke Ecke in der Mitte platziert. Diese Antwort , die nicht akzeptiert wurde, erfüllt den Wunsch des OP genauer.
Chris Schiffhauer

276

In der zum Dialog gehörenden XAML:

<Window ... WindowStartupLocation="CenterOwner">

und in C #, wenn Sie den Dialog instanziieren:

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

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

17
könnte tatsächlich var dlg = new MyDlg { Owner = this };auf dem zweiten Bit tun .
Jodrell

6
Wenn Sie ein MVVM-Muster verwenden, können Sie dieses verwenden, um den Eigentümer zu finden:dlg.Owner = Application.Current.MainWindow;
Jakob Busk Sørensen

53

Ich denke, es ist einfacher, XAML-Markup zu verwenden

<Window WindowStartupLocation="CenterOwner">

Nein, ich kann dies nicht verwenden, da der Elternteil nicht das Hauptfenster ist
Prince OfThief

6
Sie können jedes Fenster zum Eigentümer machen, indem Sie Window.Owner festlegen.
Bogdan

10
mmm CenterParentoder CenterOwner? Ich sehe nur CenterOwnerin Intellisense
Brock Hensley

@dirt Es kann davon abhängen, welche Version von WPF Sie verwenden.
BrainSlugs83

CenterOwner und CenterParent unterscheiden sich zwischen WPF und WinForms
F8ER

20

Nur im Code dahinter.

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

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

19

Ich denke, die Antworten aller auf diese Frage sind Teile dessen, was die Antwort sein sollte. Ich werde sie einfach zusammenstellen, was meiner Meinung nach der einfachste und eleganteste Ansatz für dieses Problem ist.

Erstes Setup, in dem sich das Fenster befinden soll. Hier ist es der Besitzer.

<Window WindowStartupLocation="CenterOwner">

Bevor wir das Fenster öffnen, müssen wir es dem Eigentümer geben und von einem anderen Beitrag aus können wir mit dem statischen Getter für das MainWindow der aktuellen Anwendung auf das MainWindow zugreifen.

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

Das ist es.


1
Das übergeordnete Center ist nicht vorhanden. In diesem Fall sollte WindowStartupLocation CenterOwner sein.
Umpa

1
Danke für die Information. Keine Ahnung, warum ich CenterParent gesetzt habe. Es wurde geändert.
Alex Ehlert

1
Ich weiß nicht, warum diese Lösung nicht die akzeptierte ist, es ist notwendig, um Kopfschmerzen bei der Berechnung zu vermeiden, während WPF diese als Out-of-the-Box-Lösung anbietet ...
cdie

2
Dies ist die beste Lösung.
Beyondo

1
Am Ende habe ich genau das getan, bevor ich zu dieser Antwort gescrollt habe. +1 für Sichtbarkeit!
Alexis Leclerc

8

Ich fand das am besten

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

4

Wenn Sie wenig Kontrolle über die Fenster haben, die Sie anzeigen müssen, kann das folgende Snippet hilfreich sein

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

Ich frage mich, warum dies nicht viele positive Stimmen hat. Für mich sollte das so gemacht werden. Um den Eigentümer zu zentrieren, müssen Sie den Eigentümer zuweisen, und dann funktioniert es ohne Hacks.
VPZ

3

Um ein WPF-Dialogfeld in der Mitte eines übergeordneten Windows Forms-Formulars zu positionieren, habe ich das übergeordnete Formular an das Dialogfeld übergeben, da Application.Current das übergeordnete Windows Form-Formular nicht zurückgegeben hat (ich gehe davon aus, dass es nur funktioniert, wenn die übergeordnete App WPF ist).

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

Legen Sie die WindowStartupLocation im WPF-Dialogfeld fest:

<Window WindowStartupLocation="CenterParent">

Die Art und Weise, wie Windows Form den WPF-Dialog lädt, sieht folgendermaßen aus:

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

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

2

Sie müssen ein übergeordnetes Fenster für Ihr Fenster (Eigentümer) festlegen und dann die WindowStartupLocation-Eigenschaft auf "CenterParent" setzen.


2
In WPF heißt die Eigenschaft jedoch "CenterOwner" und nicht "CenterParent".
Beta

2

Ich möchte der Antwort von Fredrik Hedblad hinzufügen, dass das Ergebnis falsch wäre, wenn die Größe des MainWindows geändert oder maximiert worden wäre, da mainWindow.Width und mainWindow.Height den in der XAML festgelegten Wert widerspiegeln.

Wenn Sie die tatsächlichen Werte möchten, können Sie mainWindow.ActualWidth und mainWindow.ActualHeight verwenden:

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

1

XAML:

    <Window WindowStartupLocation="CenterScreen">

0

Dieser Code funktioniert, wenn Sie die WindowStartupLocation-Eigenschaft in xaml nicht verwenden möchten:

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

Ich verwende "screen.WorkingArea", weil die Taskleiste das mainWindow kleiner macht. Wenn Sie das Fenster in der Mitte des Bildschirms platzieren möchten, können Sie stattdessen "screen.Bounds" verwenden.


0

Stellen Sie für das untergeordnete Fenster die XAML ein

WindowStartupLocation="CenterOwner"

Um Ihr untergeordnetes Fenster als Dialogfeld und Zentrum des übergeordneten Fensters aufzurufen, rufen Sie es über das übergeordnete Fenster auf, z

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

0

Zur Dokumentation füge ich hier ein Beispiel hinzu, wie ich etwas Ähnliches erreicht habe. Was ich brauchte, war ein Popup, das den gesamten Inhaltsbereich des übergeordneten Fensters (mit Ausnahme der Titelleiste) abdeckte, aber das einfache Zentrieren des Dialogfelds und das Erweitern des Inhalts funktionierte nicht, da das Dialogfeld immer etwas nach unten versetzt war.

Hinweis zur Benutzererfahrung: Es ist nicht schön, das übergeordnete Fenster nicht ziehen / schließen zu können, wenn das randlose Dialogfeld angezeigt wird. Daher würde ich die Verwendung überdenken. Ich habe mich auch entschieden, dies nicht zu tun, nachdem ich diese Antwort gepostet habe, sondern werde es anderen überlassen, sie anzuschauen.

Nach einigem googeln und testen habe ich es endlich so gemacht:

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

Das DialogWindowist ein Fenster und sein Besitzer ist auf das Hauptanwendungsfenster eingestellt. Das WindowStartupLocationmuss auf eingestellt sein, Manualdamit die manuelle Positionierung funktioniert.

Ergebnis:

Kein Dialog wird angezeigt

Modaler Dialog wird angezeigt

Ich weiß nicht, ob es einen einfacheren Weg gibt, aber nichts anderes schien für mich zu funktionieren.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.