Подтвердить что ты не робот

Модальный диалог не отображается поверх других окон

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

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

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

Спасибо заранее!

4b9b3361

Ответ 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();
            }
        }