多次触发 ItemChangeEvent

ItemChangeEvent fired multiple times

我在连接到 Owncloud(Caldav、Cardav)的 Outlook 插件上工作。 我使用事件处理程序来检测用户何时删除、创建或更新联系人项目。 在这种情况下,这将通知服务器并在他这边进行更新。

storage.Aitems[storage.Aitems.Count - 1].ItemAdd += new Outlook.ItemsEvents_ItemAddEventHandler(contact_item_add);
storage.Aitems[storage.Aitems.Count - 1].ItemChange += new Outlook.ItemsEvents_ItemChangeEventHandler(contact_item_change);
((MAPIFolderEvents_12_Event)storage.Afolders[storage.Afolders.Count - 1]).BeforeItemMove += new MAPIFolderEvents_12_BeforeItemMoveEventHandler(contact_item_before_move);

当我从服务器找到新的联系人项目时,我将它们添加到地址簿文件夹中。 Outlook 检测到新项目或更新,然后触发事件处理程序。这在只有一个调用的情况下很好(我可以从服务器说这个不要再次通知服务器或者这是从用户通知服务器)但我不能因为事件被多次触发。

static void contact_item_change(object Item) {
        Microsoft.Office.Interop.Outlook.ContactItem contact = (Microsoft.Office.Interop.Outlook.ContactItem)Item;
        System.Diagnostics.Debug.WriteLine("[Modification contact]" + contact.FullName);
        // Need to know if item was created by code (server) or user
        Main.SyncContact(contact);
 }

是否可以知道项目是通过 GUI 还是在我的代码中创建的? 由于事件的多次调用,我无法设置一个变量来知道它是由用户创建的还是由我的代码创建的。

顺便说一句,我已经成功地触发了一次添加和删除:

static void contact_item_add(object Item) {
        Microsoft.Office.Interop.Outlook.ContactItem contact = (Microsoft.Office.Interop.Outlook.ContactItem)Item;
        if (Contact.GetCreatedByUserProperty(contact, "USER")) {
            if (storage.PreviousAddedContactId != contact.EntryID)
            {
                System.Diagnostics.Debug.WriteLine("[Ajout contact]" + contact.FullName);
                Main.SyncContact(contact);
                storage.PreviousAddedContactId = contact.EntryID;
            }
        }
    }


static void contact_item_before_move(object item, MAPIFolder destinationFolder, ref bool cancel) {
        if ((destinationFolder == null) || (IsDeletedItemsFolder(destinationFolder))) {
            ContactItem contact = (item as ContactItem);
            if (storage.PreviousDeletedContactId != contact.EntryID)
            {
                System.Diagnostics.Debug.WriteLine("[Suppression du contact]" + contact.FullName);
                Main.DeleteContact(contact);
                storage.PreviousDeletedContactId = contact.EntryID;
            }
        }
    }

谢谢!

您可以在调用 MailItem.Save 后立即阅读 MailItem.LastModificationTime。当 ItemChange 事件触发时,您可以将新的修改时间与您缓存的时间进行比较,并检查它是否大于某个增量(1 秒?)。

如果是 Exchange 存储,您还可以检索 PR_CHANGE_KEY(DASL 名称 http://schemas.microsoft.com/mapi/proptag/0x65E20102)属性 - 每次修改后都会更改。

Is it possible to know if an item is created trough the GUI or in my code ?

不,没有任何 属性 或方法可以帮助识别用于创建 Outlook 项目的方式。但是您可以添加一个用户 属性,这可能表明该项目是由您的代码以编程方式创建的。用户创建的项目不会设置此 属性。

我遵循了 Dmitry Streblechenko 的回答 事实上,ContactItem 有一个 LastModificationTime 属性。我不知道我是否错了,但我猜 outlook 在他进行更改时永远不会更改此日期时间。所以很容易检查用户是否触摸了联系人。这允许我通知服务器并且它工作得很好!谢谢 !

static void contact_item_change(object Item) {
        Microsoft.Office.Interop.Outlook.ContactItem contact = (Microsoft.Office.Interop.Outlook.ContactItem)Item;
        // Need to know if item was created by code (server) or user
        var seconds = (DateTime.Now - contact.LastModificationTime).TotalSeconds;
        if (seconds < 2) {
            System.Diagnostics.Debug.WriteLine("[Modification contact]" + contact.FullName);
            Main.SyncContact(contact);
        }
    }

您只需要关注该项目所需的属性。当 ItemChange 事件 解雇后,您可以将该项目的属性与您的服务器项目进行比较,如果它们不同 => do Main.SyncContact(contact);