我正在使用Visual Studio 2008中的VSTO开发一个Word 2007-2010插件。在我的插件中,我需要为每个打开的Word文档创建一个自定义任务窗格。基本上,我需要为每个文档创建一个任务窗格,在文档窗口中显示正确的任务窗格,在文档关闭时执行某些操作,然后删除该任务窗格以及所有对它的引用。
到目前为止,我已经完成了以下工作:
任务窗格创建
我为每个新打开或现有的加载文档创建一个自定义任务窗格,方法如下:
在CreateTaskPaneWrapper方法中,我会检查一个Dictionary<Document, TaskPaneWrapper>,如果文档的任务窗格已经存在。我这样做是因为如果我尝试打开已经打开的文档,打开事件会触发。如果不存在,我会创建一个新的TaskPaneWrapper类。在它的构造函数中,我会创建一个新的任务窗格,并将其添加到CustomTaskPanes集合中。
所有这些似乎都很好运作,任务窗格已创建,绑定到相应的窗口,并成功删除。但是我仍然有一个问题 - 当我启动 Word 时,会打开一个空白文档。如果我在不更改空白文档的情况下打开现有文档,则空白文档及其窗口将被删除,而不触发 Document.Close、Application.DocumentBeforeClose 和 Microsoft.Office.Tools.Word.Document.Shutdown 事件。由于 OnShutdown 没有被调用,因此空白文档的任务窗格没有被删除,下一个文档窗口包含两个任务窗格 - 其中一个是最新的,另一个是第一个(被遗弃的)任务窗格。如何删除这个被遗弃的任务窗格?访问已删除的文档或窗口引用会引发 COMException(“对象已被删除”)。我正在临时使用以下方法:
在CreateTaskPaneWrapper方法中,我会检查所有现有包装器的此属性,并关闭其中属性为false的包装器。当然,捕获异常有点昂贵,而且这个解决方案相当hacky,所以我想知道,是否有更好的解决方案?在这个问题中 CustomTaskPane.Window属性被检查是否为空,但它从未对我返回null。
另外,我当前的逻辑还可能遇到其他问题吗?管理多个文档的多个任务窗格的典型方式是什么?
到目前为止,我已经完成了以下工作:
任务窗格创建
我为每个新打开或现有的加载文档创建一个自定义任务窗格,方法如下:
((ApplicationEvents4_Event) Application).NewDocument += CreateTaskPaneWrapper;
Application.DocumentOpen += CreateTaskPaneWrapper;
foreach (Document document in Application.Documents)
{
CreateTaskPaneWrapper(document);
}
在CreateTaskPaneWrapper方法中,我会检查一个Dictionary<Document, TaskPaneWrapper>,如果文档的任务窗格已经存在。我这样做是因为如果我尝试打开已经打开的文档,打开事件会触发。如果不存在,我会创建一个新的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方法中,我会检查所有现有包装器的此属性,并关闭其中属性为false的包装器。当然,捕获异常有点昂贵,而且这个解决方案相当hacky,所以我想知道,是否有更好的解决方案?在这个问题中 CustomTaskPane.Window属性被检查是否为空,但它从未对我返回null。
另外,我当前的逻辑还可能遇到其他问题吗?管理多个文档的多个任务窗格的典型方式是什么?