WPF: Jak ustawić pozycję okna dialogowego, aby była wyświetlana w środku aplikacji?

86

Jak ustawić pozycję .ShowDialog();okna dialogowego, która pochodzi z, aby była wyświetlana na środku pliku mainWindows.

W ten sposób staram się ustawić pozycję.

private void Window_Loaded(object sender, RoutedEventArgs e)
{        
    PresentationSource source = PresentationSource.FromVisual(this);
    if (source != null)
    {
        Left = ??
        Top = ??
    }
}
Prince Of Thief
źródło

Odpowiedzi:

35

Możesz spróbować zdobyć MainWindow w zdarzeniu Loaded w ten sposób

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;
}
Fredrik Hedblad
źródło
8
Spowoduje to umieszczenie lewego górnego rogu na środku. Ta odpowiedź , która nie została zaakceptowana, dokładniej spełnia życzenie PO.
Chris Schiffhauer
280

W kodzie XAML należącym do okna dialogowego:

<Window ... WindowStartupLocation="CenterOwner">

i w C # podczas tworzenia wystąpienia okna dialogowego:

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

if (dlg.ShowDialog() == true)
{
    ...
chessweb
źródło
17
mógłby faktycznie zrobić var dlg = new MyDlg { Owner = this };na drugim kawałku.
Jodrell
6
Jeśli używasz wzorca MVVM, możesz użyć tego, aby znaleźć właściciela: dlg.Owner = Application.Current.MainWindow;
Jakob Busk Sørensen
56

Myślę, że łatwiej jest używać znaczników XAML

<Window WindowStartupLocation="CenterOwner">
Najmniejszy
źródło
Nie, nie mogę tego użyć, ponieważ rodzic nie jest głównym
oknem
6
Możesz ustawić dowolne okno jako właściciela, ustawiając Window.Owner.
Bogdan
10
mmm CenterParentczy CenterOwner? Widzę tylko CenterOwnerw Intellisense
Brock Hensley,
@dirt może zależeć od używanej wersji WPF.
BrainSlugs83
CenterOwner i CenterParent różnią się odpowiednio między WPF i WinForms
F8ER
22

Tylko w kodzie.

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

        WindowStartupLocation = WindowStartupLocation.CenterOwner;
        Owner = Application.Current.MainWindow;
    }
}
Rob Dunbar
źródło
19

Myślę, że odpowiedzi wszystkich na to pytanie są częścią tego, jaka powinna być odpowiedź. Po prostu złożę je razem, co moim zdaniem jest najłatwiejszym i eleganckim podejściem do tego problemu.

Najpierw ustaw, gdzie chcesz umieścić okno. Tutaj jest właściciel.

<Window WindowStartupLocation="CenterOwner">

Przed otwarciem okna musimy podać jego właściciela iz innego wpisu możemy uzyskać dostęp do MainWindow przy użyciu statycznego gettera dla MainWindow bieżącej aplikacji.

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

Otóż ​​to.

Alex Ehlert
źródło
1
Środkowy element nadrzędny nie istnieje, w tym przypadku WindowStartupLocation powinien być CenterOwner.
Umpa
1
Dzięki, że dałeś mi znać. Nie mam pojęcia, dlaczego umieściłem CenterParent. To zostało zmienione.
Alex Ehlert
1
Nie wiem, dlaczego to rozwiązanie nie jest akceptowane, to jest to, co jest potrzebne, aby uniknąć bólów głowy związanych z obliczeniami, podczas gdy WPF ma to jako rozwiązanie
gotowe do użycia
2
To najlepsze rozwiązanie.
Beyondo
1
Skończyło się na tym, że zrobiłem dokładnie to, zanim przewiniłem do tej odpowiedzi. +1 za widoczność!
Alexis Leclerc
8

Uważam, że ten jest najlepszy

frmSample fs = new frmSample();
fs.Owner = this; // <-----
fs.WindowStartupLocation = WindowStartupLocation.CenterOwner;
var result = fs.ShowDialog();
Tim Davis
źródło
5

Jeśli masz niewielką kontrolę nad oknami, które chcesz wyświetlić, przydatny może być następujący fragment

    public void ShowDialog(Window window)
    {
        Dispatcher.BeginInvoke(
            new Func<bool?>(() =>
            {
                window.Owner = Application.Current.MainWindow;
                window.WindowStartupLocation = WindowStartupLocation.CenterOwner;
                return window.ShowDialog();
            }));
    }
Rahul Misra
źródło
Zastanawiam się, dlaczego to nie ma wielu pozytywnych głosów. Dla mnie tak NALEŻY to zrobić. Aby wyśrodkować właściciela, musisz przypisać właściciela, a wtedy działa bez hacków.
VPZ
3

Aby ustawić okno dialogowe WPF w środku formularza nadrzędnego Windows Forms, przekazałem formularz nadrzędny do okna dialogowego, ponieważ Application.Current nie zwrócił elementu nadrzędnego formularza systemu Windows (zakładam, że działa tylko wtedy, gdy aplikacja nadrzędna to 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;
    }
}

ustaw WindowStartupLocation w oknie dialogowym WPF:

<Window WindowStartupLocation="CenterParent">

a sposób, w jaki formularz systemu Windows ładuje okno dialogowe WPF, wygląda następująco:

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

if (dlg.ShowDialog() == true)
{
    ...
Jason
źródło
2

Musisz ustawić okno nadrzędne w swoim oknie (właściciel), a następnie ustawić właściwość WindowStartupLocation na „CenterParent”

Ugo Robain
źródło
2
To prawda, że ​​w WPF właściwość nazywa się „CenterOwner”, a nie „CenterParent”.
wersja beta
2

Chciałbym dodać do odpowiedzi Fredrik Hedblad, że jeśli rozmiar MainWindows został zmieniony lub zmaksymalizowany, wynik byłby nieprawidłowy, ponieważ mainWindow.Width i mainWindow.Height odzwierciedlają wartości ustawione w XAML.

Jeśli chcesz poznać rzeczywiste wartości, możesz użyć mainWindow.ActualWidth i 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;
    }
Nicolò Carandini
źródło
1

XAML:

    <Window WindowStartupLocation="CenterScreen">
GET1NE
źródło
0

Ten kod działa, jeśli nie chcesz używać właściwości WindowStartupLocation w 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);
    }
}

Używam „screen.WorkingArea”, ponieważ pasek zadań sprawia, że ​​mainWindow jest mniejsze. Jeśli chcesz umieścić okno na środku ekranu, możesz zamiast tego użyć „screen.Bounds”.

Markus
źródło
0

W przypadku okna podrzędnego ustaw XAML

WindowStartupLocation="CenterOwner"

Aby nazwać swoje okno podrzędne jako okno dialogowe i środek rodzica, wywołaj je z okna nadrzędnego, np

private void ConfigButton_OnClick(object sender, RoutedEventArgs e)
{
    var window = new ConfigurationWindow
    {
        Owner = this
    };
    window.ShowDialog();
}
sky91
źródło
0

Ze względu na dokumentację dodam tutaj przykład, w jaki sposób osiągnąłem coś podobnego. Potrzebowałem wyskakującego okienka, które obejmowało cały nadrzędny obszar zawartości okna (z wyjątkiem paska tytułu), ale po prostu wyśrodkowanie okna dialogowego i rozciągnięcie jego zawartości nie działało, ponieważ okno dialogowe zawsze było nieco przesunięte od dołu.

Uwaga na temat wrażeń użytkownika: Nie jest miło nie móc przeciągać / zamykać okna nadrzędnego, gdy wyświetlane jest okno dialogowe bez obramowania, więc ponownie rozważę jego użycie. Postanowiłem również nie robić tego po opublikowaniu tej odpowiedzi, ale pozostawiam to innym do obejrzenia.

Po pewnym googlowaniu i testowaniu w końcu udało mi się to zrobić w ten sposób:

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

DialogWindowJest okno, a jego właściciel jest ustawiony do głównego okna aplikacji. WindowStartupLocationMusi być ustawionyManual do ręcznego pozycjonowania do pracy.

Wynik:

Brak okna dialogowego

Wyświetlane jest okno dialogowe modalne

Nie wiem, czy jest na to łatwiejszy sposób, ale wydawało mi się, że nic innego nie działa.

Shahin Dohan
źródło