Обратитесь к активному окну в WPF?

Как я могу ссылаться на активное окно приложения WPF в С#, используя что-то вроде свойства ActiveForm в WinForms?


person pkain    schedule 10.01.2010    source источник


Ответы (5)


Одним из возможных способов было бы просмотреть список открытых окон в приложении и проверить, какое из них имеет IsActive = true:

Application.Current.Windows.OfType<Window>().SingleOrDefault(x => x.IsActive);

Не уверен, что может быть более одного активного окна, если, например, отображается модальное диалоговое окно, и в этом случае владелец диалогового окна и само диалоговое окно могут быть активны.

person Aviad P.    schedule 10.01.2010
comment
Снова взглянув на мой старый ответ, может быть лучше использовать оператор OfType<Window>() вместо Cast<Window>() на всякий случай... - person Aviad P.; 20.06.2012
comment
Потрясающие! Это избавляет меня от необходимости передавать ссылку на окно, что избавляет мою структуру данных от ссылок на пользовательский интерфейс. Спасибо! - person BrokeMyLegBiking; 08.03.2013
comment
Чтобы сделать его более надежным, вы также можете использовать FirstOrDefault вместо SingleOrDefault, который выдает исключение, если есть несколько совпадающих элементов. Плюс это должно быть немного быстрее, потому что он принимает первый результат и не нужно проверять, что он единственный. - person ygoe; 25.10.2013
comment
Иногда и FirstOrDefault, и SingleOrDefault возвращают null, что означает отсутствие окон с IsActive как true. Как это возможно? - person digitguy; 08.04.2014
comment
Если само приложение не активно может быть? - person Aviad P.; 08.04.2014

Есть лучший способ сделать это с помощью PInvoke. Ответ Авиада не работает все время (есть некоторые крайние случаи с диалогами).

IntPtr active = GetActiveWindow();

ActiveWindow = Application.Current.Windows.OfType<Window>()
    .SingleOrDefault(window => new WindowInteropHelper(window).Handle == active);

Сначала необходимо включить следующий импорт:

[DllImport("user32.dll")]
static extern IntPtr GetActiveWindow();
person ghord    schedule 17.10.2012
comment
Хе-хе. Мне потребовалось несколько часов, чтобы обнаружить это самому. На самом деле я написал то же самое, что и вы, и пришел сюда, чтобы поделиться этим, но вы были первыми, так что вот мой голос :P - person Erti-Chris Eelmaa; 15.01.2013
comment
не могли бы вы уточнить, что такое крайние случаи? - person nchaud; 24.04.2013
comment
@nchaud Я использую AvalonDock, который позволяет перетаскивать рабочее пространство из главного окна в новое окно. Однако эти окна также помечены IsActive. Использование другого решения вызвало исключение (SingleOrDefault выдает, если есть более одного совпадения с предикатом) или не дало мне фактическое активное окно при использовании FirstOrDefault - person clcto; 08.08.2014

Я знаю, что это немного старый вопрос, но я думаю, что мой ответ может кому-то помочь.

Моя проблема заключалась в следующем: у меня было приложение WPF MVVM, и мне нужно было получить мой экземпляр MainWindow во втором представлении, то есть во второй модели представления, чтобы установить видимость кнопки строки заголовка на visible.

Это мое решение:

MainWindow window = (MyApp.MainWindow)App.Current.MainWindow;
window.btnSearch.Visibility = System.Windows.Visibility.Visible;

Надеюсь, это поможет кому-то.

person NutCracker    schedule 20.07.2017

У меня проблемы с этим способом "Application.Current.Windows.OfType().SingleOrDefault(x => x.IsActive);" особенно потому, что я создавал приложение с главным окном, тогда у меня были проблемы при выборе главного окна. Я разрешаю это, создавая это:

В каком-то базовом классе или App.xaml.cs создайте это:

       public static Window ActivatedWindow {get;set;}

Затем поместите свой базовый класс, производный от окна, или все события активации вашего окна:

Первый вариант — персональный базовый класс окна:

       public class MetroToolWindowBase
       {
         public MetroToolWindowBase()
         {   
            Activated += new EventHandler(MakeActive); 
         }   
         private void MakeActive(object sender, EventArgs e)
         {
        App.ActivatedWindow= this;
         }
       }

Второй вариант — в активированном событии Windows:

   private void XWindow_Activated(object sender,EventArgs e)
    {
     App.ActivatedWindow= this;
    }
person Richard Aguirre    schedule 17.12.2016

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

Код:

var activeWindow = Application.Current?.Windows.OfType<Window>().FirstOrDefault(w => w.IsActive);

if (window != null)
{
    window.Owner = activeWindow;
    window.DataContext = viewModel;
}

Я заметил, что когда у меня была точка останова в другом классе, и я нажал F5, чтобы добраться до точки останова в приведенном выше коде, возвращенное activeWindow было нулевым, и каким-то образом это привело к исчезновению моего диалогового окна.

Это можно решить с помощью следующего обходного пути:

#if DEBUG
    if (activeWindow == null)
    {
        activeWindow = Application.Current?.MainWindow;
        // Or just force Topmost = true
    }
#endif

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

Я провел еще несколько проб и ошибок и обнаружил, что эта проблема возникает, когда диалоговое окно имеет следующее свойство: ShowInTaskbar="False". Когда я установил для него значение true, диалоговое окно появилось даже с нулевым владельцем.

Другой обходной путь состоял в том, чтобы установить Topmost="True", тогда я также мог сохранить свое свойство ShowInTaskbar.

Я не знаю, что происходит, но если у кого-то есть больше информации об этом, я был бы очень признателен.

person Shahin Dohan    schedule 23.06.2021