Thomas Montagnoni
Thomas Montagnoni

Reputation: 468

ItemChangeEvent fired multiple times

I work on Outlook addin that is connected to an Owncloud (Caldav, Cardav). I use eventhandlers to detect when a user delete, create or update a contact item. In this case this will notify the server and do an update on his side.

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);

When i find new contacts items from the server i add them right the addressbook folder. Outlook detect a new item or a update and then fire the eventshandlers. This is good in case there is only one call (I can say this from the server dont notify again the server or this is from the user notify the server) but i can't because the events are fired multiple times.

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);
 }

Is it possible to know if an item is created trough the GUI or in my code ? I can't set a variable to know if it was created by user or by my code because of the multiple calls of events.

BTW i already succeed to fire add and delete only one time :

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;
            }
        }
    }

Thank you !

Upvotes: 1

Views: 860

Answers (4)

sonmt
sonmt

Reputation: 66

You only need to focus on properties you want on that Item. When ItemChange event fired, you can compare properties of that Item with your server Item, if they are difference => do Main.SyncContact(contact);

Upvotes: 0

Thomas Montagnoni
Thomas Montagnoni

Reputation: 468

I followed the answer of Dmitry Streblechenko In fact ContactItem have a LastModificationTime property. I don't know if i'm wrong but i guess outlook never change this Datetime when he makes changes. So it's easy to check if user have touch the contact. That allow me to notify the server and it works very well ! Thank you !

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);
        }
    }

Upvotes: 0

Eugene Astafiev
Eugene Astafiev

Reputation: 49455

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

No, there is no property or method which can help in identifying the way which was used to create an Outlook item. But you may add a user property which may indicate that the item was created by your code programmatically. User created item will not have this property set.

Upvotes: 0

Dmitry Streblechenko
Dmitry Streblechenko

Reputation: 66296

You can read MailItem.LastModificationTime immediately after calling MailItem.Save. When ItemChange event fires, you can compare the new modification time with what you cached and check if it is greater than some delta (1 second?).

In case of Exchange store, you can also retrieve PR_CHANGE_KEY (DASL name http://schemas.microsoft.com/mapi/proptag/0x65E20102) property - it will change after each modification.

Upvotes: 1

Related Questions