3

I'm developing an extension for Visual Studio 2017 which contains custom "toolwindow". This "toolwindow" contains WPF control with a view model subscribed to the Workspace.WorkspaceChanged and EnvDTE.DTE.Events.WindowEvents.WindowActivated events.

I know that when the "toolwindow" is closed by user it's not actually destroyed but rather "hidden". However, it still reacts to my events.

So, I want to know answers for two questions:

  1. How to check that the tool window is hidden?
  2. Can I "close" the tool window so it will be destroyed?

EDIT: The code to create tool window:

protected virtual TWindow OpenToolWindow()
{
        ThreadHelper.ThrowIfNotOnUIThread();

        // Get the instance number 0 of this tool window. This window is single instance so this instance
        // is actually the only one.
        // The last flag is set to true so that if the tool window does not exists it will be created.
        ToolWindowPane window = Package.FindToolWindow(typeof(TWindow), id: 0, create: true);

        if (window?.Frame == null)
        {
            throw new NotSupportedException("Cannot create tool window");
        }

        IVsWindowFrame windowFrame = (IVsWindowFrame)window.Frame;
        Microsoft.VisualStudio.ErrorHandler.ThrowOnFailure(windowFrame.Show());
        return window as TWindow;
}
SENya
  • 1,083
  • 11
  • 26

2 Answers2

5

To detect when a toolwindow is closed, you can inherit it from IVsWindowFrameNotify3 and in the OnShow method check for fShow == (int)__FRAMESHOW.FRAMESHOW_WinClosed.

Sergey Vlasov
  • 26,641
  • 3
  • 64
  • 66
  • 1
    Thank you very much. I've actually found another way via subscription to EnvDTE80.WindowVisibilityEvents WindowShowing / WindowHiding. Are there any pitfalls with this method? – SENya Apr 02 '19 at 09:53
  • @SENya Interesting! I've no personal experience working with WindowVisibilityEvents. – Sergey Vlasov Apr 02 '19 at 16:32
2

Just to add to @Sergey Vlasov's answer - I found a second method to be notified if window is hidden/shown. Here's the code from my WPF control view model.

EnvDTE.DTE dte = MyVSPackage.Instance.GetService<EnvDTE.DTE>();

// _visibilityEvents is a private field. 
// There is a recommendation to store VS events objects in a field 
// to prevent them from being GCed
_visibilityEvents = (dte?.Events as EnvDTE80.Events2)?.WindowVisibilityEvents;

if (_visibilityEvents != null)
{
    _visibilityEvents.WindowShowing += VisibilityEvents_WindowShowing;
    _visibilityEvents.WindowHiding += VisibilityEvents_WindowHiding;
}
SENya
  • 1,083
  • 11
  • 26