wpf detect open window

10,429

Solution 1

You could create a LoadWindow() method in WindowB that you can call to load (or refresh) the data & that will work regardless of if the window is already open or not. Have it take a delegate to call when this window gets closed:

private Action ParentCallbackOnClose;

public void LoadWindow( Action parentCallbackOnClose ) {
    // load the data (set the DataContext or whatever)

    ParentCallbackOnClose = parentCallbackOnClose;    

    // Open the window and activate/bring to the foreground
    Show( );
    Activate( ); 
}

and have your window closed event call the close delegate:

private void WindowClosed( object sender, EventArgs e ) {
     ParentCallbackOnClose.Invoke( );
}

Now, from your class that opens Window B, have it hold onto that instance it opens, so that if WindowB is already open when someone tries to reload it, it just calls LoadWindow on the existing instance. Something like...

private WindowB WinB;

private void LoadWindowB(Content content)
{
    if (WinB == null ){
        WinB = new WindowB( );
    }
    WinB.LoadWindow(content, WindowBClosed);
}

And then you can just have it null out WinB on that close callback so if WinB is closed, then the next time LoadWindowB() is called it will create a new instance of it:

private void WindowBClosed( ){
    WinB = null;
}

Solution 2

Since this is the first link Google listed, which posted several years ago, for a solution to check if a Window is already open, I'll post my answer, for others, which I find easier to implement. The ChildWindow is only called from MainWindow so no other Window will need to do any checks.

private void OpenChildWindow()
{
    if (this.OwnedWindows.OfType<ChildWindow>().Count() > 0)
    {
        ChildWindow Win = this.OwnedWindows.OfType<ChildWindow>().First();
        Win.Activate();
    }
    else
    {
        ChildWindow Win = new ChildWindow();
        Win.Owner = this;
        Win.Show();
    }
}

Solution 3

There is an old school way to do this using an interface. I see this in Java a lot as a way to compensate for not having delegates (correct me if I am wrong). This method will allow you to check if there is a window already open (of any kind). The original response works very well, but you can also do it the following way:

Create the interface

public interface IWindowTracker
{
    void WindowIsOpened();
    void WindowIsClosed();
}

Implement the interface on the parent (from where you are opening):

public partial class MainWindow : Window, IWindowTracker

In your constructor, accept an object that is of the IwindowTracker interface. Save the instance for future use

    IWindowTracker windowTracker;
    public ProjectManager(IWindowTracker parentWindowTracker)
    {
        windowTracker = parentWindowTracker;

        InitializeComponent();
    }

Setup the calls to the window tracker object

    protected override void OnActivated(EventArgs e)
    {
        windowTracker.WindowIsOpened();
        base.OnActivated(e);
    }

    protected override void OnClosed(EventArgs e)
    {
        windowTracker.WindowIsClosed();
        base.OnClosed(e);
    }

and finally implement the IWindowTracker in your parent WPF window

    bool windowIsOpen = false;

    public void WindowIsOpened()
    {
        windowIsOpen = true;
    }

    public void WindowIsClosed()
    {
        windowIsOpen = false;
    }

This will allow you to keep track of if the window is still open and if it is, there is no need to open a new instance of it:

        if (!windowIsOpen)
        {
            remoteProjectManager = new ProjectManager(this);
            remoteProjectManager.Show();
        }

        remoteProjectManager.Focus();

Calling show() on a closed window seems to throw an exception, so my guess is that there is some other way or that if you have closed the window, the window is technically "destroyed"

The nice thing to this is that I can detect if the window is still open and focus on it (so that it comes to the front again).

NOTE: There is a draw back to this, in that in this setup it limits you to opening only one window at a time (assuming that all your windows are implemented like this). In my case, I only ever want to have one window open besides the main window.

You might also want to check if your window is null or not, considering that it probably isn't the only window you will have to open.

Share:
10,429
nelsonwebs
Author by

nelsonwebs

Updated on June 04, 2022

Comments

  • nelsonwebs
    nelsonwebs almost 2 years

    In my WPF app (csharp) I have an event handler that when triggered will open a new window (window B) of the application and display some data. However, when the event is triggered again, if the new window (window B) is still open, I don't want to spawn another instance of window B but just update the data being displayed in the current instance. So the question is: How to detect if window B is already and only open if it is not already, otherwise just update the data?

    I found the Application.Current.Window collection but somehow that isn't working for me yet. Ideas?