I'm developing a Word 2007-2010 addin using VSTO in Visual Studio 2008. In my addin, I need a custom task pane for each open word document. Basically, I need to create a task pane for each document, show the correct task pane in the document window, do something on document close and then remove the task pane and all references to it.
This is what I have done so far:
Task pane creation
I create a custom task pane for each new, opened or existing on load document like this:
((ApplicationEvents4_Event) Application).NewDocument += CreateTaskPaneWrapper;
Application.DocumentOpen += CreateTaskPaneWrapper;
foreach (Document document in Application.Documents)
{
CreateTaskPaneWrapper(document);
}
In the CreateTaskPaneWrapper method, I check a Dictionary<Document, TaskPaneWrapper> if a task pane for a document already exists. I do this because the open event fires if I try to open an already open document. If it doesn't exist, I create a new TaskPaneWrapper class. In its constructor, I create a new task pane and add it to the CustomTaskPanes collection with
Globals.ThisAddIn.CustomTaskPanes.Add(taskPane, "Title");
According to MSDN, this associates the task pane with the currently active window.
Task pane shutdown
Both Document.Close and Application.DocumentBeforeClose events don't suit me, because they fire before before the user gives the confirmation to close the document. So I use the Microsoft.Office.Tools.Word.Document.Shutdown event in my TaskPaneWrapper class like this:
_vstoDocument = document.GetVstoObject();
_vstoDocument.Shutdown += OnShutdown;
private void OnShutdown(object sender, EventArgs eventArgs)
{
Globals.ThisAddIn.CustomTaskPanes.Remove(_taskPane);
//additional shutdown logic
}
All of this seems to work pretty well, the task panes are created, bound to the corresponding windows, and are successfully removed. However, I still have one problem - when I start Word, a blank document opens. If I then open an existing document without changing the blank one, the blank document and it's window is deleted without the Document.Close, Application.DocumentBeforeClose and Microsoft.Office.Tools.Word.Document.Shutdown events firing. Because OnShutdown is not called and the task pane for the blank document is not deleted, the next document window contains TWO task panes - the very new one, and the very first (orphaned) one. How can I remove this orphaned task pane? Accessing the deleted document or window reference throws a COMException ("Object was deleted"). I'm temporary using this hack:
//A property in my TaskPaneWrapper class
public bool IsWindowAlive()
{
try
{
var window = _vstoDocument.ActiveWindow;
return true;
}
catch (COMException)
{
return false;
}
}
In the CreateTaskPaneWrapper method, I check this property for all existing wrappers and shutdown the ones where the property is false. Catching an exception is somewhat expensive, of course, and this solution is pretty hacky, so I was wondering, is there a better one? In this question CustomTaskPane.Window property is checked for null, but it never returns null for me.
Also, are there any other problems I can run into using my current logic? What's the typical way of managing multiple task panes for multiple documents?