【问题标题】:Outlook VSTO Explorer.Selection_Change doesn not get called未调用 Outlook VSTO Explorer.Selection_Change
【发布时间】:2020-05-09 15:43:12
【问题描述】:

在我的 VSTO 插件中,我使用以下类成员来存储指向 currentExplorer、currentAppointmentItem 和 currentExplorers 的指针。

在 Startup 中,我尝试设置所有必要的事件处理程序,如下所示:

currentExplorers = this.Application.Explorers;

foreach (Outlook.Explorer explorer in currentExplorers)
{
    ((Outlook.ExplorerEvents_10_Event)explorer).Activate +=
    new Outlook.ExplorerEvents_10_ActivateEventHandler(
    Explorer_Activate);

    explorer.Deactivate += new
    Outlook.ExplorerEvents_10_DeactivateEventHandler(
    Explorer_Deactivate);
}

currentExplorers.NewExplorer += New_Explorer;

我的事件处理程序如下所示:

void New_Explorer(Outlook.Explorer explorer)
        {
            if (currentExplorer != null)
            {
                Marshal.ReleaseComObject(currentExplorer);
            }
            currentExplorer = explorer;
            currentExplorer.SelectionChange += new Outlook.ExplorerEvents_10_SelectionChangeEventHandler(Selection_Change);
            currentExplorer.Deactivate += new Outlook.ExplorerEvents_10_DeactivateEventHandler(Explorer_Deactivate);

        }

        void Explorer_Deactivate()
        {
            if (currentExplorer != null)
            {
                currentExplorer.SelectionChange -= new Outlook.ExplorerEvents_10_SelectionChangeEventHandler(Selection_Change); ;
                Marshal.ReleaseComObject(currentExplorer);
                currentExplorer = null;
            }

        }

        void Explorer_Activate()
        {
            if (currentExplorer != null)
            {
                Marshal.ReleaseComObject(currentExplorer);
            }
            currentExplorer = this.Application.ActiveExplorer();
            currentExplorer.SelectionChange += new Outlook.ExplorerEvents_10_SelectionChangeEventHandler(Selection_Change);
        }


        private void Selection_Change()
        {
            if (currentExplorer == null)
            {
                return;
            }

            try
            {
                Outlook.MAPIFolder selectedFolder = currentExplorer.CurrentFolder;
                if (currentExplorer.Selection.Count > 0)
                {
                    Object selObject = currentExplorer.Selection[1];
                    if (selObject is Outlook.AppointmentItem)
                    {
                        if (currentAppointmentItem != null)
                        {
                            Marshal.ReleaseComObject(currentAppointmentItem);
                        }
                        currentAppointmentItem = (Outlook.AppointmentItem)selObject;
                    }
                    else
                    {
                        currentAppointmentItem = null;
                    }
                }
            } catch(Exception ex)
            {
                log.Error(ex.Message);
            }
        }

我在每个事件处理程序上设置断点 问题是当我调试我的 Outlook 插件时,除了 Explorer_Deactivate 之外,没有任何事件处理程序被调用。当我在那里调试时,我看到 currentExplorer 仍然为空,所以我认为它在 Outlook 初始化期间由于某种原因被调用(当时只有 Outlook 的初始屏幕可见)

我做错了什么? 我原以为任何项目(在邮件、日历等中)的每一个选择都会调用 Selection_Change,但不幸的是,情况并非如此

【问题讨论】:

    标签: vsto outlook-addin


    【解决方案1】:

    要触发事件,您必须始终保持源对象处于活动状态,因此您需要在全局范围(即类级别)声明对象引用。

    您在代码中混合了两种方法 - Activate/Deactivate 处理程序和 NewExplorer/Close 事件。正如我之前写的那样,您可以处理NewExplorer 事件,而不是处理ActivateDeactivate 事件,您可以在其中订阅CloseSelectionChange 事件。在Close 事件处理程序中,您可以取消订阅SelectionChange 事件。因此,您可以开发一个 Explorer 包装器。请参阅Implement a wrapper for inspectors and track item-level events in each inspector 了解更多信息。

    【讨论】:

      【解决方案2】:

      尤金的回答部分正确。 要正确使用 New_Explorer 和 Close_Explorer,需要知道要捕获 Close 事件,您需要像这样投射 Explorer:

          ((Outlook.ExplorerEvents_10_Event)currentExplorer).Close += new Outlook.ExplorerEvents_10_CloseEventHandler(Explorer_Close);
      

      但这不起作用的真正原因是据我了解:资源管理器指的是当前的 Outlook 窗口。在 ThisAddIn.Startup 完成后,不能完全确定 Outlook 窗口是否打开。因此,上面的编码将完美地处理 Outlook 的其他窗口,但不是当前的。

      因此,您需要在 Startup 中手动调用 New_Explorer 以使用 ActiveExplorer() 窗口初始化 currentExplorer 成员(该类的成员以保持引用从 Garbage Colllection 中保存)。

      New_Explorer(this.Application.ActiveExplorer());
      

      这不仅初始化了指向 currentExplorer 的指针,还设置了 Selection_Change() 和 Close() 事件处理程序。

      现在所有选择事件都得到了正确处理。 请记住,Selection_Change 似乎被多次触发:

      不幸的是,在调试器中运行此解决方案时,当用户双击约会系列并选择单个约会时,插件仍然崩溃。没有触发异常。看到这个问题仍然有效:Outlook VSTO Handling SelectionChange correctly (currently doubleclick crashes Addin)

      【讨论】:

        猜你喜欢
        • 2016-11-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-11-28
        • 2014-05-10
        • 2023-04-03
        • 2016-02-09
        • 2021-12-28
        相关资源
        最近更新 更多