VSTO 加载项 CustomTaskPane 在升级到 Word 2016/2019 后自行打开
VSTO Add-In CustomTaskPane opens itself after upgrading to Word 2016/2019
我们通过 VSTOContrib.
开发了带有 CustomTaskPanes 和 MVVM 支持的 Word 2010 的 Word VSTO 加载项
升级到 Word 2016/2019 后,我们的 CustomTaskPanes 会随机显示,用户无需执行任何操作。
似乎 Word 在使用 CustomTaskPane 时会注意到并希望下次自动(重新)打开它。
例如,在打开 new/exisitng 文档时会打开 CustomTaskPane。不会那么糟糕,如果它不会出现故障(打开,关闭,打开,关闭,......)直到它关闭或保持打开状态。
如果 CustomTaskPane 保持打开状态,则它不可用,因为它没有由我们的加载项加载的 DataContext。
ThisAddIn 中的此代码 creates/removes CustomTaskPanes:
public CustomTaskPane AddTaskPane(UserControl userControl, string title, Window owner)
{
return CustomTaskPanes.Add(userControl, title, owner);
}
public void RemoveTaskPane(CustomTaskPane taskPane)
{
if (taskPane == null)
return;
CustomTaskPanes.Remove(taskPane);
}
RibbonViewModel(每个 Document/Window 的 ViewModel)这样调用代码。
_addInHelper
具有 creating/removing CustomTaskPanes 的事件以通过回调到达 ThisAddIn
代码和 returns CustomTaskPane 实例。它还使用 IoC 容器来解析视图 "CustomTaskPaneView"
.
// Gets called when a new Window opens or a new Document is opened
public override void Intialize(Document document)
{
// ...
CreateCustomTaskPane();
// ...
}
private void CreateCustomTaskPane()
{
if (_customTaskPane != null)
return;
_addInHelper.AddTaskPane("CustomTaskPaneView", "Custom headline", CurrentWindow, result =>
{
_customTaskPane = result;
});
if (_customTaskPane == null)
{
_log.Error(...);
return;
}
_customTaskPane.DockPositionRestrict = MsoCTPDockPositionRestrict.msoCTPDockPositionRestrictNoHorizontal;
_customTaskPane.Width = Settings.Default.TaskPaneWidth;
_customTaskPane.DockPosition = Settings.Default.TaskPanePosition;
// TaskPane height and width are saved seperately for DockPositionFloating
if (_customTaskPane.DockPosition != MsoCTPDockPosition.msoCTPDockPositionFloating)
{
// Set height and width for DockPositionFloating.
// If the user drags the TaskPane to Floating, it will have the correct size.
var oldDockPosition = _customTaskPane.DockPosition;
_customTaskPane.DockPosition = MsoCTPDockPosition.msoCTPDockPositionFloating;
_customTaskPane.Height = Settings.Default.TaskPaneHeight;
_customTaskPane.Width = Settings.Default.TaskPaneWidth;
_customTaskPane.DockPosition = oldDockPosition;
}
else
{
_customTaskPane.Height = Settings.Default.TaskPaneHeight;
_customTaskPane.Width = Settings.Default.TaskPaneWidth;
}
// Saving/updating settings in these
_customTaskPane.VisibleChanged += ContentControlsTaskPane_OnVisibleChanged;
_customTaskPane.DockPositionChanged += ContentControlsTaskPane_OnDockPositionChanged;
}
关闭Window/Document时调用这段代码:
public override void Cleanup()
{
if (_customTaskPane != null)
{
SaveCustomTaskPaneProperties();
_contentControlsTaskPane.VisibleChanged -= ContentControlsTaskPane_OnVisibleChanged;
_contentControlsTaskPane.DockPositionChanged -= ContentControlsTaskPane_OnDockPositionChanged;
// Checks if the COM Object was cleaned up already
if (!_contentControlsTaskPane.IsDisposed())
{
// Tried to manually close the CustomTaskPane, but didn't help either
if (_contentControlsTaskPane.Visible)
_contentControlsTaskPane.Visible = false;
// Cleanup the CustomTaskPane ViewModel instance
var taskPaneViewModel = _contentControlsTaskPane.GetViewModel();
taskPaneViewModel?.Dispose();
_addInHelper.RemoveTaskPane(_contentControlsTaskPane);
}
}
}
这仅在使用 Word 2016 和 2019(我们不使用 2013)时发生,而在 Word 2010 中根本不会发生。
在出于测试目的将 VSTO 项目升级到 VSTO 加载项 2013 和 2016 后,它并没有变得更好。
示例:
我没有找到任何可能导致此问题的 Word 选项。
知道这可能导致什么以及如何解决这个问题/获得解决方法吗?
编辑
这是更新后的代码示例WordTaskPanesBug
重现步骤:
- 启动 Word/运行 项目
- 单击 "Open" 按钮
- 单击 "New document" 按钮
- 单击 "New document" 按钮,任务窗格打开(但这次不会出现故障)
CustomTaskPane 在示例项目中关闭文档时也会出现故障,但在我们的真实项目中不会。
Old example gif
我添加了索引来指示正在显示哪个任务窗格,这表明第二次创建新文档时添加的任务窗格来自第一个文档(创建新文档时关闭的那个)第一次,可能是因为它是空的)。
我认为您 运行 遇到的问题是这个:Creating and managing custom task panes for multiple documents in a VSTO Word addin
我们通过 VSTOContrib.
开发了带有 CustomTaskPanes 和 MVVM 支持的 Word 2010 的 Word VSTO 加载项
升级到 Word 2016/2019 后,我们的 CustomTaskPanes 会随机显示,用户无需执行任何操作。
似乎 Word 在使用 CustomTaskPane 时会注意到并希望下次自动(重新)打开它。
例如,在打开 new/exisitng 文档时会打开 CustomTaskPane。不会那么糟糕,如果它不会出现故障(打开,关闭,打开,关闭,......)直到它关闭或保持打开状态。 如果 CustomTaskPane 保持打开状态,则它不可用,因为它没有由我们的加载项加载的 DataContext。
ThisAddIn 中的此代码 creates/removes CustomTaskPanes:
public CustomTaskPane AddTaskPane(UserControl userControl, string title, Window owner)
{
return CustomTaskPanes.Add(userControl, title, owner);
}
public void RemoveTaskPane(CustomTaskPane taskPane)
{
if (taskPane == null)
return;
CustomTaskPanes.Remove(taskPane);
}
RibbonViewModel(每个 Document/Window 的 ViewModel)这样调用代码。
_addInHelper
具有 creating/removing CustomTaskPanes 的事件以通过回调到达 ThisAddIn
代码和 returns CustomTaskPane 实例。它还使用 IoC 容器来解析视图 "CustomTaskPaneView"
.
// Gets called when a new Window opens or a new Document is opened
public override void Intialize(Document document)
{
// ...
CreateCustomTaskPane();
// ...
}
private void CreateCustomTaskPane()
{
if (_customTaskPane != null)
return;
_addInHelper.AddTaskPane("CustomTaskPaneView", "Custom headline", CurrentWindow, result =>
{
_customTaskPane = result;
});
if (_customTaskPane == null)
{
_log.Error(...);
return;
}
_customTaskPane.DockPositionRestrict = MsoCTPDockPositionRestrict.msoCTPDockPositionRestrictNoHorizontal;
_customTaskPane.Width = Settings.Default.TaskPaneWidth;
_customTaskPane.DockPosition = Settings.Default.TaskPanePosition;
// TaskPane height and width are saved seperately for DockPositionFloating
if (_customTaskPane.DockPosition != MsoCTPDockPosition.msoCTPDockPositionFloating)
{
// Set height and width for DockPositionFloating.
// If the user drags the TaskPane to Floating, it will have the correct size.
var oldDockPosition = _customTaskPane.DockPosition;
_customTaskPane.DockPosition = MsoCTPDockPosition.msoCTPDockPositionFloating;
_customTaskPane.Height = Settings.Default.TaskPaneHeight;
_customTaskPane.Width = Settings.Default.TaskPaneWidth;
_customTaskPane.DockPosition = oldDockPosition;
}
else
{
_customTaskPane.Height = Settings.Default.TaskPaneHeight;
_customTaskPane.Width = Settings.Default.TaskPaneWidth;
}
// Saving/updating settings in these
_customTaskPane.VisibleChanged += ContentControlsTaskPane_OnVisibleChanged;
_customTaskPane.DockPositionChanged += ContentControlsTaskPane_OnDockPositionChanged;
}
关闭Window/Document时调用这段代码:
public override void Cleanup()
{
if (_customTaskPane != null)
{
SaveCustomTaskPaneProperties();
_contentControlsTaskPane.VisibleChanged -= ContentControlsTaskPane_OnVisibleChanged;
_contentControlsTaskPane.DockPositionChanged -= ContentControlsTaskPane_OnDockPositionChanged;
// Checks if the COM Object was cleaned up already
if (!_contentControlsTaskPane.IsDisposed())
{
// Tried to manually close the CustomTaskPane, but didn't help either
if (_contentControlsTaskPane.Visible)
_contentControlsTaskPane.Visible = false;
// Cleanup the CustomTaskPane ViewModel instance
var taskPaneViewModel = _contentControlsTaskPane.GetViewModel();
taskPaneViewModel?.Dispose();
_addInHelper.RemoveTaskPane(_contentControlsTaskPane);
}
}
}
这仅在使用 Word 2016 和 2019(我们不使用 2013)时发生,而在 Word 2010 中根本不会发生。 在出于测试目的将 VSTO 项目升级到 VSTO 加载项 2013 和 2016 后,它并没有变得更好。
示例:
我没有找到任何可能导致此问题的 Word 选项。 知道这可能导致什么以及如何解决这个问题/获得解决方法吗?
编辑
这是更新后的代码示例WordTaskPanesBug
重现步骤:
- 启动 Word/运行 项目
- 单击 "Open" 按钮
- 单击 "New document" 按钮
- 单击 "New document" 按钮,任务窗格打开(但这次不会出现故障)
CustomTaskPane 在示例项目中关闭文档时也会出现故障,但在我们的真实项目中不会。
Old example gif
我添加了索引来指示正在显示哪个任务窗格,这表明第二次创建新文档时添加的任务窗格来自第一个文档(创建新文档时关闭的那个)第一次,可能是因为它是空的)。
我认为您 运行 遇到的问题是这个:Creating and managing custom task panes for multiple documents in a VSTO Word addin