DelusionX
DelusionX

Reputation: 79

Close two windows without closing a third

I have created two buttons (button1, button2), and they both have a click routedevent handler.

When button1 is clicked, it opens an instance of the second window (Window2), which run along with the main window (MainWindow).

I would like when I click button2 to close both windows (window2, MainWindow) and show a third window (Window3).

What I did so far

private async void Button1_Click(object sender, RoutedEventArgs e)
{
    var win_window2= new Window2();

    win_window2.Cursor = Cursors.Wait;
    win_window2.Show();

    //Here the Window2 is shown along with the MainWindow
}

When I click button2 I would like to close both the MainWindow and Window2

private void Button2_Click(object sender, RoutedEventArgs e)
{  
    Window3 win_window3 = new Window3();
    win_window3.Show();
    this.Close(); //close MainWindow

    //What to type here to also close win_window2?
}

What I tried so far based on this SO answer is

private void CloseAllWindows()
{
    for (int intCounter = App.Current.Windows.Count - 1; intCounter >= 0; intCounter--)
        App.Current.Windows[intCounter].Close();
}

private void Button2_Click(object sender, RoutedEventArgs e)
{
    CloseAllWindows(); //This will close also Window3
    
    Window3 win_window3 = new Window3();
    win_window3.Show();

    //What to type here to also close win_window2?
}

But the methods CloseAllWindows() and Environment.Exit(0) will also close the Window3, which I want to avoid. I want only to close MainWindow and Window2().

Any suggestions on that? Thanks a lot.

Upvotes: 2

Views: 115

Answers (1)

Peter Duniho
Peter Duniho

Reputation: 70701

If Window3 isn't already open, then how is it getting closed when you call CloseAllWindows()? I'm still not really sure I understand the question. The code you changed your question to show after my comment, seems like that should work fine.

That said, it seems to me you could easily change your code so that you just ignore the window you want to leave open. For example:

private void CloseAllWindows(Window except = null)
{
    for (int intCounter = App.Current.Windows.Count - 1; intCounter >= 0; intCounter--)
    {
        Window window = App.Current.Windows[intCounter];

        if (window != except)
        {
            window.Close();
        }
    }
}

private void Button2_Click(object sender, RoutedEventArgs e)
{
    // Ensures Window3 is open
    Window3 win_window3 = new Window3();
    win_window3.Show();

    // Closes all open windows, except the Window3 window just opened
    CloseAllWindows(win_window3);
}

You should keep in mind that the the way code is currently written, you create a new instance of each window every time you want to open it. This may or may not be correct. For example, as I said before, the only way the code you posted would close Window3 before you show it is if there's already an instance of Window3 open. That would imply that you already have one instance open, and then you decide to create and show a second instance. Which seems like not what you probably meant to do.

Related to this is the fact that WPF has an issue in it, in that when windows are created, they get subscribed to global framework events that prevent the instances from being garbage-collected after they are discarded/closed/etc. For this reason, it's generally better to only ever create one instance of any given window and reuse that instance as needed. This typically would involve maintaining static fields that store the reference, or your own private list or dictionary of instances, something like that. That's beyond the scope of your question and thus of this answer, but it's something you should consider as you work out this design.

If you already have an instance of the window that you have created and intend to reuse, then of course you should use that one, instead of creating a new instance each time. In which case, the above should be modified to simply show the instance you already have, and pass that reference to the version of CloseAllWindows() I show above. Then that method will close only all the other windows and not the one you intend to keep open, and the original instance of Window3 will be used as you meant to do, rather than creating a new instance.

There are lots of different ways to keep track of an existing instance. You could maintain a Dictionary<Type, Window>, or just have static fields or properties that store the references, or you could use the Name property of the instance to search the current application windows. For an example of the latter, see How to reference a window using a variable

Upvotes: 1

Related Questions