MS Word VSTO 插件 Find.Execute 触发 ContentControlOnEnter 事件

MS Word VSTO Addin Find.Execute fires ContentControlOnEnter event

似乎如果 Find.Execute 在 ContentControl 中找到结果,它会导致 ContentControlOnEnter 和 ContentControlOnExit 事件触发。这特别烦人,因为即使选择仍在内容控件中,退出事件也会触发,因此任何根据内容控件是否处于活动状态来设置按钮状态的代码似乎都处于不正确的状态。

给定包含单个内容控件的文档,其中包含单词 "test" 和以下代码:

// In setup
Application.ActiveDocument.ContentControlOnEnter += ActiveDocument_ContentControlOnEnter;

private void ActiveDocument_ContentControlOnEnter(Word.ContentControl ContentControl)
{
    var selRange = _Application.Selection.Range;
    _logger.Debug(m => m("Selection: {0}-{1}", selRange.Start, selRange.End));
}

//Later in another method
var finder = _Application.ActiveDocument.Range().Find;
_logger.Debug("Find.Execute start");
finder.Execute("test);
_logger.Debug("Find.Execute end");

记录以下内容:

38137 [VSTA_Main] DEBUG - Find.Execute start
38141 [VSTA_Main] DEBUG - Selection: 1-5
38149 [VSTA_Main] DEBUG - Find.Execute end

我们有很多处理 ContentControlOnEnter 和 ContentControlOnExit 事件的代码,让查找操作导致调用它们确实会造成问题!

有没有什么方法可以在不触发这些事件的情况下使用 Find.Execute?如果做不到这一点,是否有一种很好的方法来区分 Find-triggered 和真正的用户?我试过使用进入和退出事件之间的时间,但这并不可靠。

我在 Word 中遇到了类似的问题,尽管它与选择事件有关。我尝试了很多解决方案,但只有一个有帮助。在您的情况下,创建一个新字段 bool _skipEnterAndExitEvents 并在调用 finder.Execute("test) 之前将其设置为 true 并在调用之后将其设置为 false 。并在进入和退出事件处理程序中检查此字段,如果该字段为真则跳过。这个解决方案并不漂亮,看起来像 hack,但其他解决方案甚至更丑陋,并没有真正起作用。

我想我找到了一个不错的解决方案:

private bool _doIgnoreNextExit = false;

private void ActiveDocument_ContentControlOnEnter(Word.ContentControl ContentControl)
{
    if (Application.Selection.Find.Found)
    {
        _logger.Debug("Ignoring CC enter event caused by Find operation");
        _doIgnoreNextExit = true;
        return;
    }
    // Do things
}

private void ActiveDocument_ContentControlOnExit(Word.ContentControl ContentControl)
{
    if(_doIgnoreNextExit)
    {
        _logger.Debug("Ignoring fake exit");
        _doIgnoreNextExit = false;
        return;
    }
    // Do things
}