Модальное диалоговое окно не отображается поверх других окон - PullRequest
24 голосов
/ 21 июня 2011

Я использую Window.ShowDialog(), чтобы открыть модальное окно в моем приложении WPF (MVVM), но оно позволяет мне переходить к другим окнам с помощью панели задач Windows (Windows 7).

Учтите: у меня есть3 немодальные окна открываются в моем приложении.Теперь один из них открывает модальное окно, используя Window.ShowDialog().Я также установил Application.MainWindow как владелец модального окна.Это так, потому что я использую обмен сообщениями MVVM, а обработчик сообщений для открытия нового окна централизован в App.xaml.cs.Окно открывается модально - никаких проблем там нет.Тем не менее, Windows 7 позволяет мне переключаться на другие окна приложения с панели задач.Это приводит к ситуации, когда модальное окно идет за другим окном, которого я предпочитаю не иметь.

Я не могу ничего делать в других окнах, если у меня открыто модальное окно, но было бы неплохоесли модальное окно всегда оставалось сверху, пока оно открыто.Есть ли способ отключить переключение панели задач, когда модал открыт?К вашему сведению - все открытые окна, запускаемые из приложения, отображаются в виде отдельных записей на панели задач.

Заранее спасибо!

Ответы [ 5 ]

60 голосов
/ 21 июня 2011

Нет никакого кода, который бы основывал это, но похоже, что вы отключили некоторые свойства в 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();
11 голосов
/ 20 марта 2012

Просто установите свойство владельца окна в вызывающее окно. Затем активация приложения WPF на панели задач не только активирует MainWindow, но и модальное дочернее окно и выводит его на передний план.

ChildWindow C = new ChildWindow();
C.Owner = this;
C.ShowDialog();
10 голосов
/ 13 января 2012

Если для 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();
    }
}

Этот простой взлом предполагает, что все ваши дочерние окна являются модальными, но вы можете написать более сложную логику.

3 голосов
/ 07 марта 2014

В итоге я использовал комбинацию из пары ответов здесь.Принятый ответ был поначалу полезен, но, как другие люди здесь отметили, установка 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...»для вас автоматически.

1 голос
/ 05 мая 2012

Пришлось немного модифицировать.Пришлось установить владельца и активировать окно.Проверьте наличие всплывающего окна и активируйте окно, как указано ниже.

        var enumerator = Application.Current.Windows.GetEnumerator();
        while (enumerator.MoveNext())
        {
            Window window = (Window)enumerator.Current;
            if (window != null && window.GetType() == typeof(PopUpWindow))
            {
                window.Activate();
            }
        }
...