WPF: Как установить позицию диалога, чтобы показать в центре приложения?
Как установить позицию Диалога, которая пришла из .ShowDialog();
показать в центре главного окна.
Это способ, которым я пытаюсь установить позицию.
private void Window_Loaded(object sender, RoutedEventArgs e)
{
PresentationSource source = PresentationSource.FromVisual(this);
if (source != null)
{
Left = ??
Top = ??
}
}
12 ответов
Вы можете попытаться получить 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;
}
В XAML, принадлежащем диалогу:
<Window ... WindowStartupLocation="CenterOwner">
и в C#, когда вы создаете экземпляр диалога:
MyDlg dlg = new MyDlg();
dlg.Owner = this;
if (dlg.ShowDialog() == true)
{
...
Я думаю, что проще использовать разметку XAML
<Window WindowStartupLocation="CenterParent">
Просто в коде позади.
public partial class CenteredWindow:Window
{
public CenteredWindow()
{
InitializeComponent();
WindowStartupLocation = WindowStartupLocation.CenterOwner;
Owner = Application.Current.MainWindow;
}
}
Я думаю, что ответы каждого на этот вопрос являются частями того, каким должен быть ответ. Я просто соберу их вместе, что, я считаю, является самым простым и элегантным подходом к этой проблеме.
Сначала настройте, где вы хотите, чтобы окно было расположено. Здесь это владелец.
<Window WindowStartupLocation="CenterOwner">
Перед тем, как открыть окно, мы должны дать ему владельца, и из другого поста мы можем получить доступ к MainWindow, используя статический метод получения для MainWindow текущего приложения.
Window window = new Window();
window.Owner = Application.Current.MainWindow;
window.Show();
Вот и все.
Если у вас мало контроля над окнами, которые вам нужно показать, следующий фрагмент может быть полезен
public void ShowDialog(Window window)
{
Dispatcher.BeginInvoke(
new Func<bool?>(() =>
{
window.Owner = Application.Current.MainWindow;
window.WindowStartupLocation = WindowStartupLocation.CenterOwner;
return window.ShowDialog();
}));
}
Я нашел этот лучший
frmSample fs = new frmSample();
fs.Owner = this; // <-----
fs.WindowStartupLocation = WindowStartupLocation.CenterOwner;
var result = fs.ShowDialog();
Чтобы заставить диалог WPF располагаться в центре родительской формы Windows Forms, я передал родительскую форму диалоговому окну, так как Application.Current не возвращал родительский бланк формы Windows (я предполагаю, что он работает только в том случае, если родительское приложение - 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)
{
...
Вы должны установить родительское окно для своего окна (Владелец), а затем установить для свойства WindowStartupLocation значение "CenterParent"
Я хотел бы добавить к ответу Фредрика Хедблада, что если бы 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;
}
Ради документации я добавлю здесь пример того, как я добился чего-то подобного. Мне нужно было всплывающее окно, охватывающее всю область содержимого родительского окна (исключая строку заголовка), но простое центрирование диалога и растяжение его содержимого не работали, потому что диалог всегда был немного смещен снизу.
Примечание о пользовательском опыте: не приятно не иметь возможность перетаскивать / закрывать родительское окно, когда отображается диалоговое окно без полей, поэтому я бы пересмотрел его использование. Я также решил не делать этого после публикации этого ответа, но оставлю это на усмотрение других.
После некоторого поиска в 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
для ручного позиционирования на работу.
Результат:
Я не знаю, есть ли более простой способ сделать это, но больше ничего не помогало мне.
Этот код работает, если вы не хотите использовать свойство 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", потому что панель задач делает главное окно меньше. Если вы хотите разместить окно посередине экрана, вы можете использовать вместо него "screen.Bounds".
Для дочернего окна установите на XAML
WindowStartupLocation="CenterOwner"
Чтобы вызвать ваше дочернее окно в качестве диалога и центра родительского окна, вызовите его из родительского окна, например,
private void ConfigButton_OnClick(object sender, RoutedEventArgs e)
{
var window = new ConfigurationWindow
{
Owner = this
};
window.ShowDialog();
}