P
pkelley
Using Windows XP, running Outlook 2007, C#, Visual Studio 2005 with VSTO SE.
I have an Outlook AddIn that monitors calendar Appointments.
The AddIn is working great, but I've noticed a strange anomoly:
If I add a NEW Appointment, I expect to that my "Calendar_ItemAdd" event
handler will fire (only once).
If I change an EXISTING Appointment, I expect that my
"Calendar_ItemChange" event handler will fire (only once).
Real Behavior:
If I add a NEW Appointment, my "Calendar_ItemAdd" event handler fires (as
expected), but then my "Calendar_ItemChange" event fires 15 seconds later,
and then my "Calendar_ItemChange" event fires AGAIN, another 15 seconds later.
I'm confused. Why is Outlook 2007 calling my "Calendar_ItemChange" event
handler, when I create a single, NEW Appointment?
Here's the code that monitors the "OlDefaultFolders.olFolderCalendar" folder:
public class CalendarMonitor
{
private NameSpace m_session;
private List<string> m_folderPaths;
private List<MAPIFolder> m_calendarFolders;
private List<Items> m_calendarItems;
private List<Items> m_deletedItems;
private MAPIFolder m_deletedItemsFolder;
private MAPIFolder m_calFolder;
public event EventHandler<EventArgs<AppointmentItem>>
AppointmentAdded;
public event EventHandler<EventArgs<AppointmentItem>>
AppointmentModified;
public event EventHandler<CancelEventArgs<AppointmentItem>>
AppointmentDeleting;
// Constructor
public CalendarMonitor(NameSpace session)
{
m_folderPaths = new List<string>();
m_calendarFolders = new List<MAPIFolder>();
m_calendarItems = new List<Items>();
m_deletedItems = new List<Items>();
m_session = session;
m_deletedItemsFolder =
session.GetDefaultFolder(OlDefaultFolders.olFolderDeletedItems);
m_calFolder =
session.GetDefaultFolder(OlDefaultFolders.olFolderCalendar);
HookupDefaultCalendarEvents();
} // End constructor CalendarMonitor()
public void Shutdown()
{
UnhookCalendarEvents();
m_folderPaths.Clear();
m_folderPaths = null;
m_calendarFolders.Clear();
m_calendarFolders = null;
m_calendarItems.Clear();
m_calendarItems = null;
m_deletedItems.Clear();
m_deletedItems = null;
m_session = null;
m_deletedItemsFolder = null;
m_calFolder = null;
AppointmentAdded = null;
AppointmentModified = null;
AppointmentDeleting = null;
} // End Shutdown()
private void HookupDefaultCalendarEvents()
{
if ((m_calFolder != null) && (m_deletedItemsFolder != null))
{
HookupCalendarEvents();
}
} // End HookupDefaultCalendarEvents()
private void HookupCalendarEvents()
{
if (m_calFolder.DefaultItemType != OlItemType.olAppointmentItem)
{
throw new ArgumentException("The MAPIFolder 'm_calFolder'
must use AppointmentItems as the default type.");
}
// Check for duplicate entries. Helps prevent double-ups on
event listeners.
if (m_folderPaths.Contains(m_calFolder.FolderPath) == false)
{
Items items = m_calFolder.Items;
m_folderPaths.Add(m_calFolder.FolderPath);
Items delItems = m_deletedItemsFolder.Items;
// Storing a reference to the folder and to the items
collection
// keeps folder alive. This keeps the ref count up and
prevents
// the problem of intermittent release of the COM object due
to
// garbage collection, which in turn causes events to NOT
fire.
m_calendarFolders.Add(m_calFolder);
m_calendarItems.Add(items);
m_deletedItems.Add(delItems);
// Now add event listeners.
items.ItemChange +=
new
ItemsEvents_ItemChangeEventHandler(Calendar_ItemChange);
items.ItemAdd +=
new ItemsEvents_ItemAddEventHandler(Calendar_ItemAdd);
delItems.ItemAdd +=
new ItemsEvents_ItemAddEventHandler(Calendar_ItemDelete);
}
}
private void UnhookCalendarEvents()
{
foreach (Items curItem in m_calendarItems)
{
curItem.ItemChange -=
new
ItemsEvents_ItemChangeEventHandler(Calendar_ItemChange);
curItem.ItemAdd -=
new ItemsEvents_ItemAddEventHandler(Calendar_ItemAdd);
}
foreach (Items curItem in m_deletedItems)
{
curItem.ItemAdd -=
new ItemsEvents_ItemAddEventHandler(Calendar_ItemDelete);
}
}
private void Calendar_ItemAdd(object item)
{
if (item is AppointmentItem)
{
// Verify that our event handler is defined.
if (this.AppointmentAdded != null)
{
// Notify "Add" event listener.
this.AppointmentAdded(this,
new
EventArgs<AppointmentItem>((AppointmentItem)item));
}
}
}
private void Calendar_ItemChange(object item)
{
if (item is AppointmentItem)
{
// Verify that our event handler is defined.
if (this.AppointmentModified != null)
{
// Notify "Modify" event listener.
this.AppointmentModified(this,
new
EventArgs<AppointmentItem>((AppointmentItem)item));
}
}
}
private void Calendar_ItemDelete(object item)
{
if (item is AppointmentItem)
{
if (this.AppointmentDeleting != null)
{
CancelEventArgs<AppointmentItem> args =
new
CancelEventArgs<AppointmentItem>((AppointmentItem)item);
this.AppointmentDeleting(this, args);
}
}
}
} // End class CalendarMonitor
public class EventArgs<T> : EventArgs
{
private T m_value;
public EventArgs(T aValue)
{
m_value = aValue;
}
public T Value
{
get { return m_value; }
set { m_value = value; }
}
}
I have an Outlook AddIn that monitors calendar Appointments.
The AddIn is working great, but I've noticed a strange anomoly:
If I add a NEW Appointment, I expect to that my "Calendar_ItemAdd" event
handler will fire (only once).
If I change an EXISTING Appointment, I expect that my
"Calendar_ItemChange" event handler will fire (only once).
Real Behavior:
If I add a NEW Appointment, my "Calendar_ItemAdd" event handler fires (as
expected), but then my "Calendar_ItemChange" event fires 15 seconds later,
and then my "Calendar_ItemChange" event fires AGAIN, another 15 seconds later.
I'm confused. Why is Outlook 2007 calling my "Calendar_ItemChange" event
handler, when I create a single, NEW Appointment?
Here's the code that monitors the "OlDefaultFolders.olFolderCalendar" folder:
public class CalendarMonitor
{
private NameSpace m_session;
private List<string> m_folderPaths;
private List<MAPIFolder> m_calendarFolders;
private List<Items> m_calendarItems;
private List<Items> m_deletedItems;
private MAPIFolder m_deletedItemsFolder;
private MAPIFolder m_calFolder;
public event EventHandler<EventArgs<AppointmentItem>>
AppointmentAdded;
public event EventHandler<EventArgs<AppointmentItem>>
AppointmentModified;
public event EventHandler<CancelEventArgs<AppointmentItem>>
AppointmentDeleting;
// Constructor
public CalendarMonitor(NameSpace session)
{
m_folderPaths = new List<string>();
m_calendarFolders = new List<MAPIFolder>();
m_calendarItems = new List<Items>();
m_deletedItems = new List<Items>();
m_session = session;
m_deletedItemsFolder =
session.GetDefaultFolder(OlDefaultFolders.olFolderDeletedItems);
m_calFolder =
session.GetDefaultFolder(OlDefaultFolders.olFolderCalendar);
HookupDefaultCalendarEvents();
} // End constructor CalendarMonitor()
public void Shutdown()
{
UnhookCalendarEvents();
m_folderPaths.Clear();
m_folderPaths = null;
m_calendarFolders.Clear();
m_calendarFolders = null;
m_calendarItems.Clear();
m_calendarItems = null;
m_deletedItems.Clear();
m_deletedItems = null;
m_session = null;
m_deletedItemsFolder = null;
m_calFolder = null;
AppointmentAdded = null;
AppointmentModified = null;
AppointmentDeleting = null;
} // End Shutdown()
private void HookupDefaultCalendarEvents()
{
if ((m_calFolder != null) && (m_deletedItemsFolder != null))
{
HookupCalendarEvents();
}
} // End HookupDefaultCalendarEvents()
private void HookupCalendarEvents()
{
if (m_calFolder.DefaultItemType != OlItemType.olAppointmentItem)
{
throw new ArgumentException("The MAPIFolder 'm_calFolder'
must use AppointmentItems as the default type.");
}
// Check for duplicate entries. Helps prevent double-ups on
event listeners.
if (m_folderPaths.Contains(m_calFolder.FolderPath) == false)
{
Items items = m_calFolder.Items;
m_folderPaths.Add(m_calFolder.FolderPath);
Items delItems = m_deletedItemsFolder.Items;
// Storing a reference to the folder and to the items
collection
// keeps folder alive. This keeps the ref count up and
prevents
// the problem of intermittent release of the COM object due
to
// garbage collection, which in turn causes events to NOT
fire.
m_calendarFolders.Add(m_calFolder);
m_calendarItems.Add(items);
m_deletedItems.Add(delItems);
// Now add event listeners.
items.ItemChange +=
new
ItemsEvents_ItemChangeEventHandler(Calendar_ItemChange);
items.ItemAdd +=
new ItemsEvents_ItemAddEventHandler(Calendar_ItemAdd);
delItems.ItemAdd +=
new ItemsEvents_ItemAddEventHandler(Calendar_ItemDelete);
}
}
private void UnhookCalendarEvents()
{
foreach (Items curItem in m_calendarItems)
{
curItem.ItemChange -=
new
ItemsEvents_ItemChangeEventHandler(Calendar_ItemChange);
curItem.ItemAdd -=
new ItemsEvents_ItemAddEventHandler(Calendar_ItemAdd);
}
foreach (Items curItem in m_deletedItems)
{
curItem.ItemAdd -=
new ItemsEvents_ItemAddEventHandler(Calendar_ItemDelete);
}
}
private void Calendar_ItemAdd(object item)
{
if (item is AppointmentItem)
{
// Verify that our event handler is defined.
if (this.AppointmentAdded != null)
{
// Notify "Add" event listener.
this.AppointmentAdded(this,
new
EventArgs<AppointmentItem>((AppointmentItem)item));
}
}
}
private void Calendar_ItemChange(object item)
{
if (item is AppointmentItem)
{
// Verify that our event handler is defined.
if (this.AppointmentModified != null)
{
// Notify "Modify" event listener.
this.AppointmentModified(this,
new
EventArgs<AppointmentItem>((AppointmentItem)item));
}
}
}
private void Calendar_ItemDelete(object item)
{
if (item is AppointmentItem)
{
if (this.AppointmentDeleting != null)
{
CancelEventArgs<AppointmentItem> args =
new
CancelEventArgs<AppointmentItem>((AppointmentItem)item);
this.AppointmentDeleting(this, args);
}
}
}
} // End class CalendarMonitor
public class EventArgs<T> : EventArgs
{
private T m_value;
public EventArgs(T aValue)
{
m_value = aValue;
}
public T Value
{
get { return m_value; }
set { m_value = value; }
}
}