Модальный диалог не отображается поверх других окон
Я использую Window.ShowDialog()
, чтобы открыть модальное окно в моем приложении WPF (MVVM), но он позволяет перейти к другим окнам с помощью панели задач Windows (Windows 7).
Рассмотрим это:
У меня есть 3 немодальных окна, открытых в моем приложении. Теперь один из них открывает модальное окно, используя Window.ShowDialog()
. Я также установил Application.MainWindow
в качестве владельца модального окна. Это связано с тем, что я использую обмен сообщениями MVVM, а обработчик сообщений для открытия нового окна централизуется в App.xaml.cs
. Окно открывается модально - никаких проблем нет. Однако Windows 7 позволяет мне переключиться на другие окна приложений с панели задач. Это приводит к ситуации, когда модальное окно выходит за другое окно, которое я предпочитаю не иметь.
Я не могу ничего делать в других окнах, пока у меня модальный открытый, но было бы неплохо, если модальное окно всегда оставалось на вершине, пока оно открыто. Есть ли способ отключить переключение панели задач, когда модаль открыт? FYI - все открытые окна, запущенные из приложения, отображаются как отдельные записи на панели задач.
Спасибо заранее!
Ответы
Ответ 1
Для этого не существует никакого кода, но похоже, что вы оставили некоторые свойства в Window
, которые вы создали и ожидали ShowDialog
применить дополнительную семантику диалога:
Window window = new Window()
{
Title = "Modal Dialog",
ShowInTaskbar = false, // don't show the dialog on the taskbar
Topmost = true, // ensure we're Always On Top
ResizeMode = ResizeMode.NoResize, // remove excess caption bar buttons
Owner = Application.Current.MainWindow,
};
window.ShowDialog();
Ответ 2
Просто установите свойство владельца окна в вызывающее окно. Затем активация приложения WPF на панели задач не только активирует MainWindow, но также модальное дочернее окно и выводит его на передний план.
ChildWindow C = new ChildWindow();
C.Owner = this;
C.ShowDialog();
Ответ 3
Установка Topmost в True (Topmost = True) заставляет диалоговое окно находиться в верхней части всех окон в системе (не только в приложении).
Итак, вы можете попробовать зарегистрировать событие, активированное в главном окне:
Activated += WindowActivated;
и активируйте окно владельца модального диалога каждый раз, когда активируется другое главное окно приложения.
private void WindowActivated(object sender, EventArgs e)
{
Window window = Application.Current.Windows.OfType<YourMainWindow>().FirstOrDefault(p => p != this && !p.IsActive && p.OwnedWindows.Count > 0);
if (window != null)
{
window.Activate();
}
}
Этот простой хак предполагает, что все окна ваших детей являются модальными, но вы можете написать более сложную логику.
Ответ 4
В итоге я использовал комбинацию из двух ответов. Принятый ответ был полезен сначала, но, поскольку другие люди здесь указали, что установка Topmost = true
означает, что окно всегда находится над любыми другими запущенными приложениями. Мое решение было следующим:
var myWindow = new MyWindowType();
myWindow.Owner = Application.Current.Windows.OfType<Window>().SingleOrDefault(x => x.IsActive);
Я изначально использовал:
myWindow.Owner = Application.Current.MainWindow;
Однако этот метод вызывает проблемы, если у вас открыто три окна:
MainWindow
|
-----> ChildWindow1
|
-----> ChildWindow2
Затем установка ChildWindow2.Owner = Application.Current.MainWindow
установит владельца окна в качестве окна его дедушки, а не родительского окна.
Чтобы ускорить процесс, я добавил его как фрагмент кода в Visual Studio. Если вы добавили следующее в Инструменты → Диспетчер фрагментов кода → Мои фрагменты кода:
<CodeSnippets
xmlns="http://schemas.microsoft.com/VisualStudio/2010/CodeSnippet">
<CodeSnippet Format="1.0.0">
<Header>
<Title>MVVM Set owner of page to be current active window</Title>
<Shortcut>owner</Shortcut>
</Header>
<Snippet>
<Code Language="CSharp">
<![CDATA[System.Windows.Application.Current.Windows.OfType<Window>().SingleOrDefault(x => x.IsActive);]]>
</Code>
</Snippet>
</CodeSnippet>
</CodeSnippets>
Ввод "владельца" и двойное нажатие клавиши табуляции автоматически добавит часть "Application.CurrentWindows...
".
Ответ 5
Придется немного изменить.
Мне пришлось установить владельца и активировать окно.
Проверьте всплывающее окно и активируйте окно, как показано ниже.
var enumerator = Application.Current.Windows.GetEnumerator();
while (enumerator.MoveNext())
{
Window window = (Window)enumerator.Current;
if (window != null && window.GetType() == typeof(PopUpWindow))
{
window.Activate();
}
}