Version

Recurring Appointments

The Ultimate UI for Windows Forms 2004 Volume 2 release of WinSchedule™ includes support for Recurring Appointments. The existing Appointment object has been modified to support the concept of recurrence, where an appointment is made to occur cyclically, based on a pattern that is dictated by the associated AppointmentRecurrence object. The AppointmentRecurrence object is new to the NAS2004 Volume 2 release; when it is associated with an Appointment (by being assigned to the Appointment’s Recurrence property), it causes the Appointment to serve as a "template" that generates the individual occurrences.

To enable the creation of recurring appointments, the AllowRecurringAppointments property of the associated WinCalendarInfo component must be set to True, as the value defaults to false to provide backward compatibility.

The AppointmentRecurrence Object

To support the Recurring Appointments feature, a new object was added to the UltraWinSchedule assembly - the AppointmentRecurrence object. The AppointmentRecurrence object defines the frequency at which the Appointment recurs, as well as the range of dates that include activity generated by the recurrence. To make an Appointment become a recurring appointment, an instance of the AppointmentRecurrence object is created, and then assigned to the Appointment’s Recurrence property. When the AppointmentRecurrence is assigned to an Appointment, the values of any properties of the AppointmentRecurrence that have not been explicitly set are automatically obtained from the Appointment. For example, if the AppointmentRecurrence object’s RangeStartDate property has not been set, the value is obtained from the Appointment’s StartDateTime property.

When an Appointment’s Recurrence property is set to an instance of the AppointmentRecurrence object, that Appointment is said to become a "recurring appointment root". The Appointment’s IsRecurringAppointmentRoot property will return true for these appointments, and the AppointmentRecurrence object’s RootAppointment property returns a reference to that Appointment. A recurring appointment root belongs to the associated UltraCalendarInfo element’s Appointments collection, but the occurrences that it generates do not . These appointments are referred to a "non-modified occurrences". When one of these occurrences is modified in any way, it becomes what we refer to as a "variance". Unlike the non-modified occurrences, variances are added to the associated UltraCalendarInfo element’s Appointments collection. If a recurring appointment root is removed from the Appointments collection, then all appointments that were associated with its recurrence, modified or not, are removed along with it.

The following table lists the properties of the AppointmentRecurrence object, along with a brief description of how the property behaves.

Property Type Description

Id

System.Guid

Returns a globally unique identifier that identifies this instance. Any variances associated with this instance will have the same value assigned to their RecurrenceId property, providing a means by which to link the AppointmentRecurrence and any modified occurrences. This linking mechanism is used by the serialization and data binding mechanisms to associate variances with the AppointmentRecurrence that generated them.

Description

String

Returns the human-readable description of this instance. Contains information about the recurrence frequency, and the starting and ending date and time. Example: For a recurrence that begins on Jan. 1, 2006, recurs daily, is limited to 10 occurrences, and spans from 8AM to 8:30AM, the Description property would return the following string: " Occurs every day effective 1/1/2004 until 1/10/2006 from 8AM to 8:30AM. "

OccurrenceDuration

TimeSpan

Gets/sets the duration of each occurrence in the recurrence. Note that if the OccurrenceDuration property is set such that it would cause occurrences to overlap, an exception is thrown. An example of this is the case where the PatternFrequency is set to "Daily", and the OccurrenceDuration is then set to a TimeSpan of more than 24.0 hours.

OccurrenceStartTime

DateTime

Gets/sets the start time for each non-modified occurrence in the recurrence. The default value is DateTime.MinValue; unless specifically set, the actual value is obtained from the Appointment object referenced by the RootAppointment property.

PatternDayOfMonth

Integer

Gets/sets the number of the day in its respective month on which each occurrence will occur. Applicable only when the PatternFrequency property is set to "Monthly" or "Yearly".

The default value is 0; unless specifically set, the actual value is obtained from the Appointment object referenced by the RootAppointment property.

Note: If the PatternDayOfMonth property is set to a value that exceeds the number of days in any of the months that the recurrence spans, the occurrence for those months will fall on the last day of that month.

PatternDaysOfWeek

RecurrencePatternDaysOfWeek

Gets/sets the day(s) of the week on which each occurrence occurs. The default value is None; unless specifically set, the actual value is obtained from the Appointment object referenced by the RootAppointment property.

Note: The DayOfWeek property is expressed as bit flags, so that multiple days can be represented by the property.

Example: To specify that a recurrence should occur on Tuesdays and Thursdays, assign a value of: (4 OR 16 ) = 20

PatternFrequency

RecurrencePatternFrequency

Gets/sets the frequency at which the recurrence occurs: daily, weekly, monthly, or yearly.

PatternInterval

Integer

Gets/sets the interval between occurrences of the recurrence. Works in conjunction with the PatternFrequency property. Not applicable when the PatternFrequency property is set to "Yearly".

Example: If the PatternFrequency property is set to "Weekly", and the PatternInterval property is set to 2, the appointment occurs every other week.

PatternMonthOfYear

Integer

Gets/sets the month of the year in which the recurrence will occur. Applicable only when the PatternFrequency property is set to "Yearly". The default value is based on the month of year that coincides with the RangeStartDate property.

PatternOccurrenceOfDayInMonth

RecurrencePatternDayInMonth

Gets/sets whether the recurrence should occur on the first, second, third, fourth or last occurrence of the day of the week corresponding to the PatternDaysOfWeek property in its respective month. Applicable only when the PatternType property is set to "Calculated" (which is only applicable when the PatternFrequency property is set to "Monthly" or "Yearly"). The default value is None; unless specifically set, the actual value is obtained from the RangeStartDate property.

PatternType

RecurrencePatternType

Gets/sets whether the recurrence pattern is based on a specific day of the month and/or month of the year, or if it is calculated based on other criteria. Only applicable when the PatternFrequency property is set to "Monthly" or "Yearly". If the PatternFrequency property is set to "Monthly", and the PatternType property is set to "Explicit", the PatternDayOfMonth and PatternInterval properties are used to determine the recurrence pattern. If the PatternFrequency property is set to "Monthly", and the PatternType is set to "Calculated", the OccurrenceOfDayInMonth, PatternDaysOfWeek, and PatternInterval properties are used to determine the recurrence pattern. If the PatternFrequency property is set to "Yearly", and the PatternType is set to "Explicit", the recurrence occurs once per year, in the month specified by the PatternMonthOfYear property, and on the day specified by the PatternDayOfMonth property. If the PatternFrequency property is set to "Yearly", and the PatternType is set to "Calculated", the recurrence occurs once per year, on a day which is determined by a combination of the PatternOccurrenceOfDayInMonth, PatternDaysOfWeek, and PatternMonthOfYear properties.

RangeEndDate

DateTime

Gets/sets the start time for each non-modified occurrence in the recurrence. The default value is DateTime.MinValue; unless specifically set, the actual value is obtained from the Appointment object referenced by the RootAppointment property.

RangeLimit

RecurrenceRangeLimit

Gets/sets the limiting factor of the recurrence (i.e., whether it never ends, ends after a certain number of occurrences, or ends on or before a certain date).

RangeMaxOccurrences

Integer

Gets/sets the maximum number of occurrences for the recurrence. Applicable only when the RangeLimit property is set to "LimitByNumberOfOccurrences".

RangeStartDate

DateTime

Gets/sets the date that defines the beginning of the recurrence. Note: The first occurrence of the recurrence does not necessarily begin on this date, but will never occur earlier than this date.

RootAppointment

Appointment

Gets/sets the Appointment object that fully describes all occurrences (except for the date and start/end time) of "non-modified" occurrences. This Appointment acts as a template that describes the subject, location, etc. of each member of the recurrence. Note: Setting the StartDateTime or EndDateTime properties of an Appointment object that is assigned to an AppointmentRecurrence’s RootAppointment property will cause an exception to be thrown.

Variances

VariancesCollection

Returns a collection of the Appointments that belong to this recurrence, but deviate in some way as to not be fully described by the recurrence. This collection is actually an abstraction that returns a subset of the associated UltraCalendarInfo component’s Appointments collection; each member of the subset is an Appointment object whose RecurrenceGuid property is equal to the Guid property of this AppointmentRecurrence instance.

Appointment Object Modifications

As mentioned in the previous section, properties were added to the existing Appointment object to support recurrence. The following tables lists these new properties, along with a brief description of how the property behaves.

Property Type Description

IsRecurringAppointmentRoot

Boolean

Returns whether this Appointment represents a recurrence. This property returns true if the Appointment’s Recurrence property is set to an instance of an AppointmentRecurrence object. Appointments that are "recurring appointment roots" belong to the associated UltraCalendarInfo component’s Appointments collection, but are not realized in the user interface. This type of appointment can be thought of as a "template", which generates occurrences at a frequency that is determined by the recurring appointment root’s associated AppointmentRecurrence object. Unless modified, those occurrences acquire their Subject, Location, Description, etc., from the recurring appointment root.

IsVariance

Boolean

Returns whether this Appointment is a member of a recurrence, and has at least one property value (excluding StartDateTime and EndDateTime) that differs from that of the recurring appointment root.

IsRecurringAppointmentRoot

Boolean

Returns whether this Appointment represents a recurrence. This property returns true if the Appointment’s Recurrence property is set to an instance of an AppointmentRecurrence object. Appointments that are "recurring appointment roots" belong to the associated UltraCalendarInfo component’s Appointments collection, but are not realized in the user interface. This type of appointment can be thought of as a "template", which generates occurrences at a frequency that is determined by the recurring appointment root’s associated AppointmentRecurrence object. Unless modified, those occurrences acquire their Subject, Location, Description, etc., from the recurring appointment root.

OriginalStartDateTime

DateTime

Returns the DateTime that represents the value of the Appointment’s StartDateTime property as generated by the recurrence engine. Unless the value of the StartDateTime property is modified, the OriginalStartDateTime property returns the same value as the StartDateTime property. The OriginalStartDateTime property is necessary to support "gaps" in the recurrence, which occur when one member of the series is deleted. When the AppointmentRecurrence object generates each occurrence, it checks its Variances collection for a member whose OriginalStartDateTime coincides with the date of the occurrence; if one exists, the occurrence is omitted.

Recurrence

AppointmentRecurrence

Gets/sets the AppointmentRecurrence object that describes the recurrence pattern that determines the frequency at which occurrences occur. Note that only Appointment objects that are the RootAppointment of an AppointmentRecurrence return a non-null value from this property; "standalone" appointments (those that are not associated with a recurrence), non-modified occurrences, and variances all return null from this property. Note: Attempting to set the Recurrence property of an Appointment that is an occurrence of some other AppointmentRecurrence will cause an exception to be thrown, that is, a member of one recurrence cannot itself be a recurring appointment root. Also, assigning an AppointmentRecurrence object that is already assigned to some other Appointment’s Recurrence property results in an exception being thrown, that is, an AppointmentRecurrence can only service one appointment at a time.

RecurrenceId

System.Guid

Returns the globally unique identifier that refers to the AppointmentRecurrence object to which this Appointment is associated. Note: If the Appointment is not a member of a recurrence, the property returns Guid.Empty.

RecurringAppointmentRoot

Appointment

Returns the Appointment object whose associated AppointmentRecurrence defines this Appointment’s recurrence criteria. "Standalone" appointments and root appointments both return null for this property.

The RecurrenceDialog

Users of previous versions of UltraWinSchedule might be familiar with the AppointmentDialog, which looks and behaves much like the appointment dialog included with MS Outlook. To provide a front end for creating and editing recurring appointments, NAS2004 Vol 2 includes the RecurrenceDialog. Also very similar to the one seen in MS Outlook, the dialog can be launched directly from the AppointmentDialog, providing the end user with the same interface that an MS Outlook user would be accustomed to.

winschedule's recurring appointment dialog

To provide flexibility to the end developer, an event is fired before the RecurrenceDialog is displayed - BeforeDisplayAppointmentRecurrenceDialog - which can be canceled to prevent the default dialog from being displayed. A custom dialog can be displayed in its place, or no dialog at all.