WPF: Làm cách nào để đặt vị trí Hộp thoại để hiển thị ở giữa ứng dụng?


83

Cách đặt vị trí của Dialog .ShowDialog();để hiển thị ở trung tâm của MainWindows.

Đây là cách tôi cố gắng thiết lập vị trí.

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

Câu trả lời:


35

Bạn có thể thử nắm giữ MainWindow trong sự kiện Đã tải như thế này

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
Điều này đặt góc trên cùng bên trái ở trung tâm. Câu trả lời này , không được chấp nhận, hoàn thành mong muốn của OP chính xác hơn.
Chris Schiffhauer

277

Trong XAML thuộc Hộp thoại:

<Window ... WindowStartupLocation="CenterOwner">

và trong C # khi bạn khởi tạo Hộp thoại:

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

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

17
thực sự có thể làm var dlg = new MyDlg { Owner = this };trên bit thứ hai.
Jodrell

6
Nếu bạn đang sử dụng mẫu MVVM, bạn có thể sử dụng mẫu này để tìm chủ sở hữu:dlg.Owner = Application.Current.MainWindow;
Jakob Busk Sørensen,

55

Tôi nghĩ sử dụng đánh dấu xaml dễ dàng hơn

<Window WindowStartupLocation="CenterOwner">

Không, tôi không thể sử dụng điều này bởi vì cha mẹ không phải là MainWindow
Hoàng tử OfThief

6
Bạn có thể đặt bất kỳ cửa sổ nào làm chủ sở hữu bằng cách đặt Window.Owner.
Bogdan

10
mmm CenterParenthoặc CenterOwner? Tôi chỉ nhìn thấy CenterOwnertrong Intellisense
Brock Hensley

@dirt nó có thể phụ thuộc vào phiên bản WPF bạn đang sử dụng.
BrainSlugs83

CenterOwner và CenterParent khác nhau giữa WPF và WinForms, tương ứng
F8ER

21

Chỉ trong mã phía sau.

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

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

19

Tôi nghĩ câu trả lời của mọi người cho câu hỏi này là một phần của câu trả lời nên là gì. Tôi chỉ đơn giản là sẽ tập hợp chúng lại với nhau mà tôi tin là cách tiếp cận dễ dàng và dễ hiểu nhất cho vấn đề này.

Đầu tiên thiết lập nơi bạn muốn đặt cửa sổ. Đây là chủ sở hữu.

<Window WindowStartupLocation="CenterOwner">

Trước khi mở cửa sổ, chúng ta cần cung cấp cho nó chủ sở hữu và từ một bài đăng khác, chúng ta có thể truy cập MainWindow bằng cách sử dụng getter tĩnh cho MainWindow của ứng dụng hiện tại.

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

Đó là nó.


1
Trung tâm gốc không tồn tại, WindowStartupLocation phải là CenterOwner trong trường hợp này.
Umpa

1
Cảm ơn vì đã cho tôi biết. Không hiểu tại sao tôi đặt CenterParent. Nó đã được thay đổi.
Alex Ehlert

1
Tôi không biết tại sao giải pháp này không phải là người chấp nhận, đó là cần phải đau đầu tránh tính toán là gì trong khi WPF có này như out-of-the-box giải pháp ...
cdie

2
Đây là giải pháp tốt nhất.
Beyondo

1
Tôi đã làm chính xác điều này trước khi tôi cuộn đến câu trả lời này. +1 cho khả năng hiển thị!
Alexis Leclerc,

8

Tôi thấy cái này là tốt nhất

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

5

Nếu bạn có ít quyền kiểm soát các cửa sổ mà bạn cần hiển thị, đoạn mã sau có thể hữu ích

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

Tôi tự hỏi tại sao điều này không có nhiều phiếu bầu. Đối với tôi, đây là cách NÊN THỰC HIỆN. Đối với chủ sở hữu trung tâm, bạn phải chỉ định chủ sở hữu và sau đó nó hoạt động mà không bị hack.
VPZ

3

Để đưa Hộp thoại WPF vào vị trí trung tâm của biểu mẫu mẹ Windows Forms, tôi đã chuyển biểu mẫu mẹ vào hộp thoại vì Application.Current không trả về biểu mẫu gốc Windows (tôi cho rằng nó chỉ hoạt động nếu ứng dụng mẹ là 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;
    }
}

đặt WindowStartupLocation trên Hộp thoại WPF:

<Window WindowStartupLocation="CenterParent">

và cách Windows Form tải hộp thoại WPF như sau:

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

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

2

Bạn phải đặt cửa sổ chính cho cửa sổ của mình (Chủ sở hữu) và sau đó đặt thuộc tính WindowStartupLocation thành "CenterParent"


2
Đúng, trong WPF thuộc tính được gọi là "CenterOwner" chứ không phải "CenterParent".
beta

2

Tôi muốn thêm vào câu trả lời của Fredrik Hedblad rằng nếu MainWindows đã được thay đổi kích thước hoặc tối đa, kết quả sẽ sai, vì mainWindow.Width và mainWindow.Height phản ánh giá trị được đặt trên XAML.

Nếu bạn muốn các giá trị thực, bạn có thể sử dụng mainWindow.ActualWidth và 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

Mã này hoạt động nếu bạn không muốn sử dụng thuộc tính WindowStartupLocation trong 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);
    }
}

Tôi đang sử dụng "screen.WorkingArea" vì thanh tác vụ làm cho mainWindow nhỏ hơn. Nếu bạn muốn đặt cửa sổ ở giữa màn hình, bạn có thể sử dụng "screen.Bounds" để thay thế.


0

Đối với cửa sổ con, hãy đặt ở XAML

WindowStartupLocation="CenterOwner"

Để gọi cửa sổ con của bạn như một hộp thoại và trung tâm của cửa sổ chính, hãy gọi nó từ cửa sổ mẹ, ví dụ:

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

0

Để làm tài liệu, tôi sẽ thêm vào đây một ví dụ về cách tôi đạt được điều gì đó tương tự. Những gì tôi cần là một cửa sổ bật lên bao phủ toàn bộ khu vực nội dung Cửa sổ mẹ (không bao gồm thanh tiêu đề), nhưng chỉ cần căn giữa hộp thoại và kéo dài nội dung của nó không hoạt động vì hộp thoại luôn bị lệch một chút so với phía dưới.

Lưu ý về trải nghiệm người dùng: Thật không hay khi không thể kéo / đóng cửa sổ mẹ khi hộp thoại không viền đang hiển thị, vì vậy tôi sẽ xem xét lại việc sử dụng nó. Tôi cũng quyết định không làm điều này sau khi đăng câu trả lời này, nhưng sẽ để nó cho những người khác xem xét.

Sau một số googling và thử nghiệm, cuối cùng tôi đã làm được như thế này:

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

Đây DialogWindowlà một Cửa sổ và chủ sở hữu của nó được đặt thành Cửa sổ ứng dụng chính. Các WindowStartupLocationphải được đặtManual cho việc định vị bằng tay để làm việc.

Kết quả:

Không có hộp thoại nào hiển thị

Hộp thoại phương thức hiển thị

Tôi không biết có cách nào dễ dàng hơn để làm điều này không, nhưng dường như không có cách nào khác hiệu quả với tôi.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.