63

How can I refer to active Window of WPF application in C#, using something like ActiveForm property in WinForms?

Dave Clemmer
  • 3,741
  • 12
  • 49
  • 72
pkain
  • 657
  • 1
  • 6
  • 6

5 Answers5

113

One possible way would be to scan the list of open windows in the application and check which one of them has IsActive = true:

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

Not sure if there may be more than one active window if, for example, there's a modal dialog showing, in which case, the owner of the dialog and the dialog itself might be active.

Richard
  • 277
  • 5
  • 16
Aviad P.
  • 32,036
  • 14
  • 103
  • 124
  • 2
    Looking at my old answer again, it might be better to use the `OfType()` operator instead of the `Cast()` one just in case... – Aviad P. Jun 20 '12 at 08:00
  • awesome! This keeps me from having to pass a reference to the window, which keeps my data structure free of UI references. thanks! – BrokeMyLegBiking Mar 07 '13 at 22:19
  • 6
    To make it more robust, you could as well use `FirstOrDefault` instead of `SingleOrDefault` which throws an exception if there are multiple matching items. Plus it should be a tiny bit faster because it accepts the first result and doesn't need to check that it's the only one. – ygoe Oct 25 '13 at 15:04
  • 1
    Sometimes both `FirstOrDefault` and `SingleOrDefault` returns `null`, meaning there are no windows with IsActive as true. How is that possible? – digitguy Apr 08 '14 at 08:24
  • 1
    If the application itself is not active maybe? – Aviad P. Apr 08 '14 at 08:26
  • Thanks for this answer. I used LastOrDefault() to get the last active child from the list. that way it will always have the appropriate owner and never open a child window behind the parent window. – bbedson Jul 19 '22 at 21:19
30

There is better way to do this using PInvoke. Aviads answer is not working all the time (there are some edge cases with dialogs).

IntPtr active = GetActiveWindow();

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

One must include following import first:

[DllImport("user32.dll")]
static extern IntPtr GetActiveWindow();
ghord
  • 13,260
  • 6
  • 44
  • 69
  • 1
    Hehe. It took me few hours to discover this myself. I actually wrote the exact same thing as you & come here to share it, but you were first, so here's my vote :P – Erti-Chris Eelmaa Jan 15 '13 at 15:04
  • 7
    can you please elaborate on what the edge cases are? – nchaud Apr 24 '13 at 15:06
  • 2
    @nchaud I am using AvalonDock which allows you to drag a workspace out of the main window and into a new window. However, these windows are also marked `IsActive`. Using the other solution threw an exception (`SingleOrDefault` throws if there are more than one matching the predicate) or didn't give me the actual active window when using `FirstOrDefault` – clcto Aug 07 '14 at 21:06
2

I know this is a bit old question but I think my answer could help someone.

My problem was this: I had a WPF MVVM application and I needed to get my MainWindow instance in the second view, i.e. second view model, in order to set the visibility of title bar button to visible.

This is my solution:

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

Hope this would help someone.

NutCracker
  • 11,485
  • 4
  • 44
  • 68
0

I have problems With this way "Application.Current.Windows.OfType().SingleOrDefault(x => x.IsActive);" specialy because I was building an aplication with a main Window then i had problems when the main window was selected. I resolve it creating this:

In some base class or App.xaml.cs create this:

       public static Window ActivatedWindow {get;set;}

Then put in your base class deriving Window or all of your Window's Activate Event:

First Option - personal Window Base Class:

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

Second Option- In Activated Event of Windows:

   private void XWindow_Activated(object sender,EventArgs e)
    {
     App.ActivatedWindow= this;
    }
Richard Aguirre
  • 543
  • 6
  • 14
0

Another way to do it is to use the native GetActiveWindow function from user32.dll.

[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr GetActiveWindow();

To convert it to an actual WPF Window:

IntPtr handle = GetActiveWindow();

HwndSource hwndSource = HwndSource.FromHwnd(handle);
var window = hwndSource?.RootVisual as Window;

If hosting a WPF Window in a WinForms app, WindowInteropHelper should be used. This makes for example the Window owner work correctly:

var wih = new WindowInteropHelper(window)
{
    Owner = GetActiveWindow()
};

I edited my old answer because the edge case I encountered disappeared after a Visual Studio update, but it can be checked from answer history. I encountered an issue there where I was getting null for active window in certain circumstances while debugging.

Shahin Dohan
  • 6,149
  • 3
  • 41
  • 58