Пример #1
0
        //=====================================================================

        /// <summary>
        /// This is overridden to allow cloning of a PDI object
        /// </summary>
        /// <returns>A clone of the object</returns>
        public override object Clone()
        {
            VToDo o = new VToDo();

            o.Clone(this);
            return(o);
        }
Пример #2
0
        /// <summary>
        /// This is overridden to allow proper comparison of To-Do objects
        /// </summary>
        /// <param name="obj">The object to which this instance is compared</param>
        /// <returns>Returns true if the object equals this instance, false if it does not</returns>
        public override bool Equals(object obj)
        {
            VToDo td = obj as VToDo;

            if (td == null)
            {
                return(false);
            }

            // The ToString() method returns a text representation of the object based on all of its settings so
            // it's a reliable way to tell if two instances are the same.
            return(this == td || this.ToString() == td.ToString());
        }
Пример #3
0
        /// <summary>
        /// This is overridden to allow copying of the additional properties
        /// </summary>
        /// <param name="p">The PDI object from which the settings are to be copied</param>
        protected override void Clone(PDIObject p)
        {
            VToDo o = (VToDo)p;

            this.ClearProperties();

            classification = (ClassificationProperty)o.Classification.Clone();
            categories     = (CategoriesProperty)o.Categories.Clone();
            resources      = (ResourcesProperty)o.Resources.Clone();
            url            = (UrlProperty)o.Url.Clone();
            uid            = (UniqueIdProperty)o.UniqueId.Clone();
            geo            = (GeographicPositionProperty)o.GeographicPosition.Clone();
            lastMod        = (LastModifiedProperty)o.LastModified.Clone();
            dateCreated    = (DateCreatedProperty)o.DateCreated.Clone();
            startDate      = (StartDateProperty)o.StartDateTime.Clone();
            due            = (DueDateProperty)o.DueDateTime.Clone();
            completed      = (CompletedDateProperty)o.CompletedDateTime.Clone();
            timeStamp      = (TimeStampProperty)o.TimeStamp.Clone();
            summary        = (SummaryProperty)o.Summary.Clone();
            desc           = (DescriptionProperty)o.Description.Clone();
            priority       = (PriorityProperty)o.Priority.Clone();
            sequence       = (SequenceProperty)o.Sequence.Clone();
            rNum           = (RecurrenceCountProperty)o.RecurrenceCount.Clone();
            comment        = (CommentProperty)o.Comment.Clone();
            organizer      = (OrganizerProperty)o.Organizer.Clone();
            recurId        = (RecurrenceIdProperty)o.RecurrenceId.Clone();
            status         = (StatusProperty)o.Status.Clone();
            pct            = (PercentCompleteProperty)o.PercentComplete.Clone();
            duration       = (DurationProperty)o.Duration.Clone();

            this.Contacts.CloneRange(o.Contacts);
            this.Attendees.CloneRange(o.Attendees);
            this.RelatedTo.CloneRange(o.RelatedTo);
            this.Attachments.CloneRange(o.Attachments);
            this.RequestStatuses.CloneRange(o.RequestStatuses);
            this.Alarms.CloneRange(o.Alarms);
            this.CustomProperties.CloneRange(o.CustomProperties);

            base.Clone(p);
        }
Пример #4
0
        /// <summary>
        /// Add a calendar item
        /// </summary>
        /// <param name="sender">The sender of the event</param>
        /// <param name="e">The event arguments</param>
        private void btnAdd_Click(object sender, EventArgs e)
        {
            switch(cboComponents.SelectedIndex)
            {
                case 0:
                    using(CalendarObjectDlg dlg = new CalendarObjectDlg())
                    {
                        VEvent evt = new VEvent();
                        evt.UniqueId.AssignNewId(true);
                        evt.DateCreated.TimeZoneDateTime = DateTime.Now;
                        evt.LastModified.TimeZoneDateTime = evt.DateCreated.TimeZoneDateTime;
                        dlg.SetValues(evt);

                        if(dlg.ShowDialog() == DialogResult.OK)
                        {
                            dlg.GetValues(evt);

                            // Create a unique ID for the new item
                            evt.UniqueId.AssignNewId(true);

                            vCal.Events.Add(evt);
                        }
                    }
                    break;

                case 1:
                    using(CalendarObjectDlg dlg = new CalendarObjectDlg())
                    {
                        VToDo td = new VToDo();
                        td.DateCreated.TimeZoneDateTime = DateTime.Now;
                        td.LastModified.TimeZoneDateTime = td.DateCreated.TimeZoneDateTime;
                        dlg.SetValues(td);

                        if(dlg.ShowDialog() == DialogResult.OK)
                        {
                            dlg.GetValues(td);

                            // Create a unique ID for the new item
                            td.UniqueId.AssignNewId(true);

                            vCal.ToDos.Add(td);
                        }
                    }
                    break;

                case 2:
                    using(CalendarObjectDlg dlg = new CalendarObjectDlg())
                    {
                        VJournal j = new VJournal();
                        j.DateCreated.TimeZoneDateTime = DateTime.Now;
                        j.LastModified.TimeZoneDateTime = j.DateCreated.TimeZoneDateTime;
                        dlg.SetValues(j);

                        if(dlg.ShowDialog() == DialogResult.OK)
                        {
                            dlg.GetValues(j);

                            // Create a unique ID for the new item
                            j.UniqueId.AssignNewId(true);

                            vCal.Journals.Add(j);
                        }
                    }
                    break;

                case 3:
                    using(VFreeBusyDlg dlg = new VFreeBusyDlg())
                    {
                        if(dlg.ShowDialog() == DialogResult.OK)
                        {
                            VFreeBusy fb = new VFreeBusy();
                            dlg.GetValues(fb);

                            // Create a unique ID for the new item
                            fb.UniqueId.AssignNewId(true);

                            vCal.FreeBusys.Add(fb);
                        }
                    }
                    break;
            }
        }
Пример #5
0
        /// <summary>
        /// Store To-Do information from the controls
        /// </summary>
        /// <param name="td">The To-Do to use</param>
        private bool StoreToDoInfo(VToDo td)
        {
            DateTime startDate = DateTime.MinValue, endDate = DateTime.MinValue, completedDate = DateTime.MinValue;
            Duration dur = Duration.Zero;

            lblMsg.Text = null;

            // Perform some edits
            if(txtStartDate.Text.Trim().Length != 0 && !DateTime.TryParse(txtStartDate.Text,
              CultureInfo.CurrentCulture, DateTimeStyles.None, out startDate))
                lblMsg.Text = "Invalid start date format<br>";

            if(txtEndDate.Text.Trim().Length != 0 && !DateTime.TryParse(txtEndDate.Text,
              CultureInfo.CurrentCulture, DateTimeStyles.None, out endDate))
                lblMsg.Text = "Invalid end date format<br>";

            if(txtCompleted.Text.Trim().Length != 0 && !DateTime.TryParse(txtCompleted.Text,
              CultureInfo.CurrentCulture, DateTimeStyles.None, out completedDate))
                lblMsg.Text = "Invalid completed date format<br>";

            if(txtDuration.Text.Trim().Length != 0 && !Duration.TryParse(txtDuration.Text, out dur))
                lblMsg.Text += "Invalid duration format<br>";

            if(!String.IsNullOrWhiteSpace(lblMsg.Text))
                return false;

            // Unique ID is not changed
            td.LastModified.TimeZoneDateTime = DateTime.Now;

            if(txtSequence.Text.Trim().Length == 0)
                td.Sequence.SequenceNumber = 0;
            else
                td.Sequence.SequenceNumber = Convert.ToInt32(txtSequence.Text);

            if(txtPriority.Text.Trim().Length == 0)
                td.Priority.PriorityValue = 0;
            else
                td.Priority.PriorityValue = Convert.ToInt32(txtPriority.Text);

            td.StartDateTime.TimeZoneDateTime = startDate;
            td.StartDateTime.ValueLocation = ValLocValue.DateTime;
            td.DueDateTime.TimeZoneDateTime = endDate;
            td.DueDateTime.ValueLocation = ValLocValue.DateTime;
            td.CompletedDateTime.TimeZoneDateTime = completedDate;
            td.CompletedDateTime.ValueLocation = ValLocValue.DateTime;

            if(txtPercent.Text.Trim().Length == 0)
                td.PercentComplete.Percentage = 0;
            else
                td.PercentComplete.Percentage = Convert.ToInt32(txtPercent.Text);

            td.Duration.DurationValue = dur;
            td.Summary.Value = txtSummary.Text;
            td.Description.Value = txtDescription.Text;
            td.Organizer.Value = txtOrganizer.Text;
            td.Url.Value = txtUrl.Text;
            td.Comment.Value = txtComments.Text;

            // Get status value
            td.Status.StatusValue = (StatusValue)Enum.Parse(typeof(StatusValue),
                cboStatus.Items[cboStatus.SelectedIndex].ToString(), true);

            return true;
        }
Пример #6
0
        /// <summary>
        /// Load To-Do information into the controls
        /// </summary>
        /// <param name="td">The To-Do to use</param>
        private void LoadToDoInfo(VToDo td)
        {
            chkTransparent.Enabled = txtLocation.Enabled = false;

            lblEndDate.Text = "Due";

            lblUniqueId.Text = td.UniqueId.Value;
            lblTimeZone.Text = td.StartDateTime.TimeZoneId;
            txtSequence.Text = td.Sequence.SequenceNumber.ToString();
            txtPriority.Text = td.Priority.PriorityValue.ToString();

            // General
            if(td.StartDateTime.TimeZoneDateTime != DateTime.MinValue)
                txtStartDate.Text = td.StartDateTime.TimeZoneDateTime.ToString("G");

            // We'll reuse End Date for Due Date
            if(td.DueDateTime.TimeZoneDateTime != DateTime.MinValue)
                txtEndDate.Text = td.DueDateTime.TimeZoneDateTime.ToString("G");

            if(td.CompletedDateTime.TimeZoneDateTime != DateTime.MinValue)
                txtCompleted.Text = td.CompletedDateTime.TimeZoneDateTime.ToString("G");

            if(td.Duration.DurationValue != Duration.Zero)
                txtDuration.Text = td.Duration.DurationValue.ToString(Duration.MaxUnit.Weeks);

            txtPercent.Text = td.PercentComplete.Percentage.ToString();
            txtSummary.Text = td.Summary.Value;
            txtDescription.Text = td.Description.Value;
            txtOrganizer.Text = td.Organizer.Value;
            txtUrl.Text = td.Url.Value;
            txtComments.Text = td.Comment.Value;

            // Load status values and set status
            cboStatus.Items.Add("None");
            cboStatus.Items.Add("NeedsAction");
            cboStatus.Items.Add("Completed");
            cboStatus.Items.Add("InProcess");
            cboStatus.Items.Add("Cancelled");

            if(cboStatus.Items.FindByValue(td.Status.StatusValue.ToString()) == null)
                cboStatus.Items.Add(td.Status.StatusValue.ToString());

            cboStatus.SelectedValue = td.Status.StatusValue.ToString();

            dgAttendees.DataSource = td.Attendees;
            dgRecurrences.DataSource = td.RecurrenceRules;
            dgRecurDates.DataSource = td.RecurDates;
            dgExceptions.DataSource = td.ExceptionRules;
            dgExDates.DataSource = td.ExceptionDates;
            dgReqStats.DataSource = td.RequestStatuses;
        }
Пример #7
0
        //=====================================================================

        /// <summary>
        /// This is overridden to allow cloning of a PDI object
        /// </summary>
        /// <returns>A clone of the object</returns>
        public override object Clone()
        {
            VToDo o = new VToDo();
            o.Clone(this);
            return o;
        }
Пример #8
0
        /// <summary>
        /// This is implemented to handle properties as they are parsed from the data stream
        /// </summary>
        /// <param name="propertyName">The name of the property.</param>
        /// <param name="parameters">A string collection containing the parameters and their values.  If empty,
        /// there are no parameters.</param>
        /// <param name="propertyValue">The value of the property.</param>
        /// <remarks><para>There may be a mixture of name/value pairs or values alone in the parameters string
        /// collection.  It is up to the derived class to process the parameter list based on the specification
        /// to which it conforms.  For entries that are parameter names, the entry immediately following it in
        /// the collection is its associated parameter value.  The property name, parameter names, and their
        /// values may be in upper, lower, or mixed case.</para>
        /// 
        /// <para>The value may be an encoded string.  The properties are responsible for any decoding that may
        /// need to occur (i.e. base 64 encoded image data).</para></remarks>
        /// <exception cref="PDIParserException">This is thrown if an error is encountered while parsing the data
        /// stream.  Refer to the and inner exceptions for information on the cause of the problem.</exception>
        protected override void PropertyParser(string propertyName, StringCollection parameters, string propertyValue)
        {
            SpecificationVersions version = SpecificationVersions.None;
            string temp;
            int idx;

            // Is it parsing a sub-object?
            if(currentState != VCalendarParserState.VCalendar)
            {
                switch(currentState)
                {
                    case VCalendarParserState.VEvent:
                        VEventParser(propertyName, parameters, propertyValue);
                        break;

                    case VCalendarParserState.VToDo:
                        VToDoParser(propertyName, parameters, propertyValue);
                        break;

                    case VCalendarParserState.VJournal:
                        VJournalParser(propertyName, parameters, propertyValue);
                        break;

                    case VCalendarParserState.VAlarm:
                        VAlarmParser(propertyName, parameters, propertyValue);
                        break;

                    case VCalendarParserState.VFreeBusy:
                        VFreeBusyParser(propertyName, parameters, propertyValue);
                        break;

                    case VCalendarParserState.VTimeZone:
                        VTimeZoneParser(propertyName, parameters, propertyValue);
                        break;

                    case VCalendarParserState.ObservanceRule:
                        ObservanceRuleParser(propertyName, parameters, propertyValue);
                        break;

                    case VCalendarParserState.Custom:
                        CustomObjectParser(propertyName, parameters, propertyValue);
                        break;
                }

                return;
            }

            // The last entry is always CustomProperty so scan for length minus one
            for(idx = 0; idx < ntvCal.Length - 1; idx++)
                if(ntvCal[idx].IsMatch(propertyName))
                    break;

            // An opening BEGIN:VCALENDAR property must have been seen
            if(vCal == null && ntvCal[idx].EnumValue != PropertyType.Begin)
                throw new PDIParserException(this.LineNumber, LR.GetString("ExParseNoBeginProp", "BEGIN:VCALENDAR",
                    propertyName));

            // Handle or create the property
            switch(ntvCal[idx].EnumValue)
            {
                case PropertyType.Begin:
                    // Start a new object
                    temp = propertyValue.Trim();

                    // The last entry is always Custom so scan for length - 1
                    for(idx = 0; idx < ntvObjs.Length - 1; idx++)
                        if(ntvObjs[idx].IsMatch(temp))
                            break;

                    priorState.Push(currentState);
                    currentState = ntvObjs[idx].EnumValue;

                    switch(currentState)
                    {
                        case VCalendarParserState.VCalendar:
                            // NOTE: If serializing into an existing instance, this may not be null.  If so, it
                            // is ignored. It may also exist if two calendars appear in the same file.  In that
                            // case, they will be merged into one calendar.
                            if(vCal == null)
                                vCal = new VCalendar();
                            break;

                        case VCalendarParserState.VEvent:
                            vEvent = new VEvent();
                            vCal.Events.Add(vEvent);
                            break;

                        case VCalendarParserState.VToDo:
                            vToDo = new VToDo();
                            vCal.ToDos.Add(vToDo);
                            break;

                        case VCalendarParserState.VJournal:
                            vJournal = new VJournal();
                            vCal.Journals.Add(vJournal);
                            break;

                        case VCalendarParserState.VFreeBusy:
                            vFreeBusy = new VFreeBusy();
                            vCal.FreeBusys.Add(vFreeBusy);
                            break;

                        case VCalendarParserState.VTimeZone:
                            // NOTE: Unlike the other objects, time zone are not added to the collection until
                            // the END Tag is encountered as they are shared amongst all calendar instances.
                            vTimeZone = new VTimeZone();
                            break;

                        case VCalendarParserState.Custom:
                            CustomObjectParser(propertyName, parameters, propertyValue);
                            break;
                    }
                    break;

                case PropertyType.End:
                    // The value must be VCALENDAR
                    if(String.Compare(propertyValue.Trim(), "VCALENDAR", StringComparison.OrdinalIgnoreCase) != 0)
                        throw new PDIParserException(this.LineNumber, LR.GetString("ExParseUnrecognizedTagValue",
                            ntvCal[idx].Name, propertyValue));

                    // When done, we'll propagate the version number to all objects to make it consistent
                    vCal.PropagateVersion();
                    break;

                case PropertyType.Version:
                    // Version must be 1.0 or 2.0
                    temp = propertyValue.Trim();

                    if(temp == "1.0")
                        version = SpecificationVersions.vCalendar10;
                    else
                        if(temp == "2.0")
                            version = SpecificationVersions.iCalendar20;
                        else
                            throw new PDIParserException(this.LineNumber, LR.GetString("ExParseUnrecognizedVersion",
                                "vCalendar/iCalendar", temp));

                    vCal.Version = version;
                    break;

                case PropertyType.ProductId:
                    vCal.ProductId.EncodedValue = propertyValue;
                    break;

                case PropertyType.CalendarScale:
                    vCal.CalendarScale.DeserializeParameters(parameters);
                    vCal.CalendarScale.EncodedValue = propertyValue;
                    break;

                case PropertyType.Method:
                    vCal.Method.DeserializeParameters(parameters);
                    vCal.Method.EncodedValue = propertyValue;
                    break;

                case PropertyType.GeographicPosition:
                    vCal.VCalendarGeographicPosition.EncodedValue = propertyValue;
                    break;

                case PropertyType.TimeZone:
                    vCal.VCalendarTimeZone.DeserializeParameters(parameters);
                    vCal.VCalendarTimeZone.EncodedValue = propertyValue;
                    break;

                case PropertyType.Daylight:
                    vCal.VCalendarDaylightRule.DeserializeParameters(parameters);
                    vCal.VCalendarDaylightRule.EncodedValue = propertyValue;
                    break;

                default:    // Anything else is a custom property
                    CustomProperty c = new CustomProperty(propertyName);
                    c.DeserializeParameters(parameters);
                    c.EncodedValue = propertyValue;
                    vCal.CustomProperties.Add(c);
                    break;
            }
        }
Пример #9
0
        //=====================================================================

        /// <summary>
        /// This is overridden to handle the additional state maintained by the calendar parser
        /// </summary>
        /// <param name="fullReset">If true, a full reset is done (i.e. this is the start of a brand new session.
        /// If false only the line state is reset (it's done parsing a property name or value).</param>
        protected override void ResetState(bool fullReset)
        {
            if(fullReset)
            {
                currentState = VCalendarParserState.VCalendar;
                vEvent = null;
                vToDo = null;
                vJournal = null;
                vAlarm = null;
                vFreeBusy = null;
                vTimeZone = null;
                obsRule = null;

                priorState.Clear();
                beginValue.Clear();
            }

            base.ResetState(fullReset);
        }
Пример #10
0
        /// <summary>
        /// This is implemented to handle properties related to VToDo items
        /// </summary>
        /// <param name="propertyName">The name of the property.</param>
        /// <param name="parameters">A string collection containing the parameters and their values.  If empty,
        /// there are no parameters.</param>
        /// <param name="propertyValue">The value of the property.</param>
        protected virtual void VToDoParser(string propertyName, StringCollection parameters, string propertyValue)
        {
            StringCollection sc;
            string[] parts, parms;
            int idx;

            // The last entry is always CustomProperty so scan for length minus one
            for(idx = 0; idx < ntvToDo.Length - 1; idx++)
                if(ntvToDo[idx].IsMatch(propertyName))
                    break;

            // An opening BEGIN:VTODO property must have been seen
            if(vToDo == null)
                throw new PDIParserException(this.LineNumber, LR.GetString("ExParseNoBeginProp", "BEGIN:VTODO",
                    propertyName));

            // Handle or create the property
            switch(ntvToDo[idx].EnumValue)
            {
                case PropertyType.Begin:    // Handle nested objects
                    priorState.Push(currentState);

                    // Is it an alarm?
                    if(String.Compare(propertyValue.Trim(), "VALARM", StringComparison.OrdinalIgnoreCase) == 0)
                    {
                        vAlarm = new VAlarm();
                        vToDo.Alarms.Add(vAlarm);
                        currentState = VCalendarParserState.VAlarm;
                    }
                    else
                    {
                        // Unknown/custom object
                        currentState = VCalendarParserState.Custom;
                        CustomObjectParser(propertyName, parameters, propertyValue);
                    }
                    break;

                case PropertyType.End:
                    // For this, the value must be VTODO
                    if(String.Compare(propertyValue.Trim(), "VTODO", StringComparison.OrdinalIgnoreCase) != 0)
                        throw new PDIParserException(this.LineNumber, LR.GetString("ExParseUnrecognizedTagValue",
                            ntvToDo[idx].Name, propertyValue));

                    // The To-Do is added to the collection when created so we don't have to rely on an END tag
                    // to add it.
                    vToDo = null;
                    currentState = priorState.Pop();
                    break;

                case PropertyType.Class:
                    vToDo.Classification.EncodedValue = propertyValue;
                    break;

                case PropertyType.Categories:
                    // If this is seen more than once, just add the new stuff to the existing property
                    CategoriesProperty cp = new CategoriesProperty();
                    cp.DeserializeParameters(parameters);
                    cp.EncodedValue = propertyValue;

                    foreach(string s in cp.Categories)
                        vToDo.Categories.Categories.Add(s);
                    break;

                case PropertyType.Resources:
                    // If this is seen more than once, just add the new stuff to the existing property
                    ResourcesProperty rp = new ResourcesProperty();
                    rp.DeserializeParameters(parameters);
                    rp.EncodedValue = propertyValue;

                    foreach(string s in rp.Resources)
                        vToDo.Resources.Resources.Add(s);
                    break;

                case PropertyType.Url:
                    vToDo.Url.DeserializeParameters(parameters);
                    vToDo.Url.EncodedValue = propertyValue;
                    break;

                case PropertyType.UniqueId:
                    vToDo.UniqueId.EncodedValue = propertyValue;
                    break;

                case PropertyType.LastModified:
                    vToDo.LastModified.DeserializeParameters(parameters);
                    vToDo.LastModified.EncodedValue = propertyValue;
                    break;

                case PropertyType.GeographicPosition:
                    vToDo.GeographicPosition.EncodedValue = propertyValue;
                    break;

                case PropertyType.DateCreated:
                    vToDo.DateCreated.DeserializeParameters(parameters);
                    vToDo.DateCreated.EncodedValue = propertyValue;
                    break;

                case PropertyType.DueDate:
                    vToDo.DueDateTime.DeserializeParameters(parameters);
                    vToDo.DueDateTime.EncodedValue = propertyValue;
                    break;

                case PropertyType.StartDateTime:
                    vToDo.StartDateTime.DeserializeParameters(parameters);
                    vToDo.StartDateTime.EncodedValue = propertyValue;
                    break;

                case PropertyType.CompletedDate:
                    vToDo.CompletedDateTime.DeserializeParameters(parameters);
                    vToDo.CompletedDateTime.EncodedValue = propertyValue;
                    break;

                case PropertyType.TimeStamp:
                    vToDo.TimeStamp.DeserializeParameters(parameters);
                    vToDo.TimeStamp.EncodedValue = propertyValue;
                    break;

                case PropertyType.Summary:
                    vToDo.Summary.DeserializeParameters(parameters);
                    vToDo.Summary.EncodedValue = propertyValue;
                    break;

                case PropertyType.Description:
                    vToDo.Description.DeserializeParameters(parameters);
                    vToDo.Description.EncodedValue = propertyValue;
                    break;

                case PropertyType.Priority:
                    vToDo.Priority.DeserializeParameters(parameters);
                    vToDo.Priority.EncodedValue = propertyValue;
                    break;

                case PropertyType.Sequence:
                    vToDo.Sequence.DeserializeParameters(parameters);
                    vToDo.Sequence.EncodedValue = propertyValue;
                    break;

                case PropertyType.RecurrenceCount:
                    vToDo.RecurrenceCount.DeserializeParameters(parameters);
                    vToDo.RecurrenceCount.EncodedValue = propertyValue;
                    break;

                case PropertyType.Comment:
                    // If this is seen more than once, just add the new stuff to the existing property
                    if(vToDo.Comment.Value != null)
                    {
                        vToDo.Comment.EncodedValue += "\r\n";
                        vToDo.Comment.EncodedValue += propertyValue;
                    }
                    else
                    {
                        vToDo.Comment.DeserializeParameters(parameters);
                        vToDo.Comment.EncodedValue = propertyValue;
                    }
                    break;

                case PropertyType.Contact:
                    ContactProperty cont = new ContactProperty();
                    cont.DeserializeParameters(parameters);
                    cont.EncodedValue = propertyValue;
                    vToDo.Contacts.Add(cont);
                    break;

                case PropertyType.Organizer:
                    vToDo.Organizer.DeserializeParameters(parameters);
                    vToDo.Organizer.EncodedValue = propertyValue;
                    break;

                case PropertyType.Attendee:
                    AttendeeProperty ap = new AttendeeProperty();
                    ap.DeserializeParameters(parameters);
                    ap.EncodedValue = propertyValue;
                    vToDo.Attendees.Add(ap);
                    break;

                case PropertyType.RelatedTo:
                    RelatedToProperty rt = new RelatedToProperty();
                    rt.DeserializeParameters(parameters);
                    rt.EncodedValue = propertyValue;
                    vToDo.RelatedTo.Add(rt);
                    break;

                case PropertyType.Attachment:
                    AttachProperty att = new AttachProperty();
                    att.DeserializeParameters(parameters);
                    att.EncodedValue = propertyValue;
                    vToDo.Attachments.Add(att);
                    break;

                case PropertyType.RecurrenceId:
                    vToDo.RecurrenceId.DeserializeParameters(parameters);
                    vToDo.RecurrenceId.EncodedValue = propertyValue;
                    break;

                case PropertyType.Status:
                    vToDo.Status.DeserializeParameters(parameters);
                    vToDo.Status.EncodedValue = propertyValue;
                    break;

                case PropertyType.RequestStatus:
                    RequestStatusProperty rs = new RequestStatusProperty();
                    rs.DeserializeParameters(parameters);
                    rs.EncodedValue = propertyValue;
                    vToDo.RequestStatuses.Add(rs);
                    break;

                case PropertyType.PercentComplete:
                    vToDo.PercentComplete.DeserializeParameters(parameters);
                    vToDo.PercentComplete.EncodedValue = propertyValue;
                    break;

                case PropertyType.Duration:
                    vToDo.Duration.DeserializeParameters(parameters);
                    vToDo.Duration.EncodedValue = propertyValue;
                    break;

                case PropertyType.AudioAlarm:
                case PropertyType.DisplayAlarm:
                case PropertyType.EMailAlarm:
                case PropertyType.ProcedureAlarm:
                    // These are converted to a VAlarm object
                    vAlarm = new VAlarm();
                    ParseVCalendarAlarm(ntvToDo[idx].EnumValue, parameters, propertyValue);
                    vToDo.Alarms.Add(vAlarm);
                    vAlarm = null;
                    break;

                case PropertyType.RecurrenceRule:
                    RRuleProperty rr = new RRuleProperty();
                    rr.DeserializeParameters(parameters);
                    rr.EncodedValue = propertyValue;
                    vToDo.RecurrenceRules.Add(rr);
                    break;

                case PropertyType.RecurDate:
                    // There may be more than one date in the value.  If so, split them into separate ones.  This
                    // makes it easier to manage.  They'll get written back out as individual properties but
                    // that's okay.
                    parts = propertyValue.Split(',', ';');

                    // It's important that we retain the same parameters for each one
                    parms = new string[parameters.Count];
                    parameters.CopyTo(parms, 0);

                    foreach(string s in parts)
                    {
                        sc = new StringCollection();
                        sc.AddRange(parms);

                        RDateProperty rd = new RDateProperty();
                        rd.DeserializeParameters(sc);
                        rd.EncodedValue = s;

                        vToDo.RecurDates.Add(rd);
                    }
                    break;

                case PropertyType.ExceptionRule:
                    ExRuleProperty er = new ExRuleProperty();
                    er.DeserializeParameters(parameters);
                    er.EncodedValue = propertyValue;
                    vToDo.ExceptionRules.Add(er);
                    break;

                case PropertyType.ExceptionDate:
                    // There may be more than one date in the value.  If so, split them into separate ones.  This
                    // makes it easier to manage.  They'll get written back out as individual properties but
                    // that's okay.
                    parts = propertyValue.Split(',', ';');

                    // It's important that we retain the same parameters for each one
                    parms = new string[parameters.Count];
                    parameters.CopyTo(parms, 0);

                    foreach(string s in parts)
                    {
                        sc = new StringCollection();
                        sc.AddRange(parms);

                        ExDateProperty ed = new ExDateProperty();
                        ed.DeserializeParameters(sc);
                        ed.EncodedValue = s;

                        vToDo.ExceptionDates.Add(ed);
                    }
                    break;

                case PropertyType.ExcludeStartDateTime:
                    // This is a custom property not defined by the spec
                    vToDo.ExcludeStartDateTime = (propertyValue[0] == '1');
                    break;

                default:    // Anything else is a custom property
                    CustomProperty cust = new CustomProperty(propertyName);
                    cust.DeserializeParameters(parameters);
                    cust.EncodedValue = propertyValue;
                    vToDo.CustomProperties.Add(cust);
                    break;
            }
        }