我正在使用 Visual Studio 2008 中的 VSTO 开发 Word 2007-2010 插件。在我的插件中,我需要为每个打开的 Word 文档创建一个自定义任务窗格。基本上,我需要为每个文档创建一个任务窗格,在文档窗口中显示正确的任务窗格,在文档关闭时执行某些操作,然后删除任务窗格以及对它的所有引用。
这是我到目前为止所做的:
任务窗格创建
我为每个新的、打开的或现有的加载文档创建一个自定义任务窗格,如下所示:
((ApplicationEvents4_Event) Application).NewDocument += CreateTaskPaneWrapper;
Application.DocumentOpen += CreateTaskPaneWrapper;
foreach (Document document in Application.Documents)
{
CreateTaskPaneWrapper(document);
}
在 CreateTaskPaneWrapper 方法中,如果文档的任务窗格已经存在,我会检查 Dictionary<Document, TaskPaneWrapper>。我这样做是因为如果我尝试打开一个已经打开的文档,则会触发 open 事件。如果它不存在,我创建一个新的 TaskPaneWrapper 类。在其构造函数中,我创建了一个新的任务窗格并将其添加到 CustomTaskPanes 集合中
Globals.ThisAddIn.CustomTaskPanes.Add(taskPane, "Title");
根据 MSDN,这将任务窗格与当前活动窗口相关联。
任务窗格关闭
Document.Close 和 Application.DocumentBeforeClose 事件都不适合我,因为它们在用户确认关闭文档之前触发。所以我在我的 TaskPaneWrapper 类中使用 Microsoft.Office.Tools.Word.Document.Shutdown 事件,如下所示:
_vstoDocument = document.GetVstoObject();
_vstoDocument.Shutdown += OnShutdown;
private void OnShutdown(object sender, EventArgs eventArgs)
{
Globals.ThisAddIn.CustomTaskPanes.Remove(_taskPane);
//additional shutdown logic
}
所有这一切似乎工作得很好,任务窗格被创建,绑定到相应的窗口,并被成功删除。但是,我仍然有一个问题 - 当我启动 Word 时,会打开一个空白文档。如果我随后打开现有文档而不更改空白文档,则会删除空白文档及其窗口,而不会触发 Document.Close、Application.DocumentBeforeClose 和 Microsoft.Office.Tools.Word.Document.Shutdown 事件。因为没有调用 OnShutdown 并且没有删除空白文档的任务窗格,所以下一个文档窗口包含两个任务窗格 - 非常新的一个和第一个(孤立的)一个。如何删除这个孤立的任务窗格?访问已删除的文档或窗口引用会引发 COMException(“对象已删除”)。我暂时使用这个黑客:
//A property in my TaskPaneWrapper class
public bool IsWindowAlive()
{
try
{
var window = _vstoDocument.ActiveWindow;
return true;
}
catch (COMException)
{
return false;
}
}
在 CreateTaskPaneWrapper 方法中,我检查所有现有包装器的此属性并关闭属性为假的包装器。当然,捕获异常有点昂贵,而且这个解决方案非常hacky,所以我想知道,有没有更好的解决方案?在这个问题中,CustomTaskPane.Window 属性被检查为 null,但它永远不会为我返回 null。
另外,使用我当前的逻辑还有其他问题吗?为多个文档管理多个任务窗格的典型方法是什么?