/// <summary> /// Edit an exception in the exception collection /// </summary> /// <param name="source">The source of the event</param> /// <param name="e">The event arguments</param> protected void dgExceptions_EditCommand(object source, DataGridCommandEventArgs e) { // Ignore the request if the page is not valid if (!Page.IsValid) { return; } // Save changes to the prior edited item if (dgExceptions.EditItemIndex != -1) { dgExceptions_UpdateCommand(source, new DataGridCommandEventArgs( dgExceptions.Items[dgExceptions.EditItemIndex], e.CommandSource, e)); if (!Page.IsValid) { return; } } RecurringObject ro = GetCurrentObject(); dgExceptions.EditItemIndex = e.Item.ItemIndex; dgExceptions.DataSource = ro.ExceptionRules; dgExceptions.DataBind(); }
/// <summary> /// This handles the Add command for the exception data grid /// </summary> /// <param name="source">The source of the event</param> /// <param name="e">The event arguments</param> protected void dgExceptions_ItemCommand(object source, DataGridCommandEventArgs e) { if (e.CommandName == "Add") { // Save changes to the edited item if there is one if (dgExceptions.EditItemIndex != -1) { dgExceptions_UpdateCommand(source, new DataGridCommandEventArgs( dgExceptions.Items[dgExceptions.EditItemIndex], e.CommandSource, e)); } // Ignore the request if the page is not valid if (!Page.IsValid) { return; } // Add a new exception and go into edit mode on it RecurringObject ro = GetCurrentObject(); ExRuleProperty exrule = new ExRuleProperty(); exrule.Recurrence.RecurDaily(1); ro.ExceptionRules.Add(exrule); dgExceptions.EditItemIndex = ro.ExceptionRules.Count - 1; dgExceptions.DataSource = ro.ExceptionRules; dgExceptions.DataBind(); } }
/// <summary> /// Use some limitations to prevent overloading the server or timing out the page if possible /// </summary> /// <param name="ro">The recurring object</param> /// <param name="r">The recurrence to check</param> private static void ApplyLimits(RecurringObject ro, Recurrence r) { if (r.Frequency > RecurFrequency.Hourly) { r.MaximumOccurrences = 5000; } if (r.MaximumOccurrences != 0) { if (r.MaximumOccurrences > 5000) { r.MaximumOccurrences = 5000; } } else if (r.Frequency == RecurFrequency.Hourly) { if (r.RecurUntil > ro.StartDateTime.DateTimeValue.AddYears(5)) { r.RecurUntil = ro.StartDateTime.DateTimeValue.AddYears(5); } } else if (r.RecurUntil > ro.StartDateTime.DateTimeValue.AddYears(50)) { r.RecurUntil = ro.StartDateTime.DateTimeValue.AddYears(50); } }
/// <summary> /// Cancel changes to an exception in the collection /// </summary> /// <param name="source">The source of the event</param> /// <param name="e">The event arguments</param> protected void dgExceptions_CancelCommand(object source, DataGridCommandEventArgs e) { RecurringObject ro = GetCurrentObject(); dgExceptions.EditItemIndex = -1; dgExceptions.DataSource = ro.ExceptionRules; dgExceptions.DataBind(); }
/// <summary> /// Bind data to the edit item template. We have to retrieve the calendar object from session state and /// retrieve the exception item from it to set the values in the Recurrence Pattern web server control. /// </summary> /// <param name="source">The source of the event</param> /// <param name="e">The event arguments</param> protected void dgExceptions_ItemDataBound(object sender, DataGridItemEventArgs e) { if (e.Item.ItemType == ListItemType.EditItem) { RecurringObject ro = GetCurrentObject(); RecurrencePattern rpException = (RecurrencePattern)e.Item.FindControl("rpException"); rpException.SetRecurrence(ro.ExceptionRules[e.Item.ItemIndex].Recurrence); rpException.Focus(); } }
/// <summary> /// Update an exception item in the collection /// </summary> /// <param name="source">The source of the event</param> /// <param name="e">The event arguments</param> protected void dgExceptions_UpdateCommand(object source, DataGridCommandEventArgs e) { if (!Page.IsValid) { return; } RecurringObject ro = GetCurrentObject(); RecurrencePattern rpException = (RecurrencePattern)e.Item.FindControl("rpException"); Recurrence r = ro.ExceptionRules[e.Item.ItemIndex].Recurrence; r.Reset(); rpException.GetRecurrence(r); dgExceptions.EditItemIndex = -1; dgExceptions.DataSource = ro.ExceptionRules; dgExceptions.DataBind(); }
/// <summary> /// Delete an exception from the collection /// </summary> /// <param name="source">The source of the event</param> /// <param name="e">The event arguments</param> protected void dgExceptions_DeleteCommand(object source, DataGridCommandEventArgs e) { // Save changes to the edited item if it isn't the one being deleted if (dgExceptions.EditItemIndex != -1 && dgExceptions.EditItemIndex != e.Item.ItemIndex) { Page.Validate(); dgExceptions_UpdateCommand(source, new DataGridCommandEventArgs( dgExceptions.Items[dgExceptions.EditItemIndex], e.CommandSource, e)); if (!Page.IsValid) { return; } } RecurringObject ro = GetCurrentObject(); ro.ExceptionRules.RemoveAt(e.Item.ItemIndex); dgExceptions.EditItemIndex = -1; dgExceptions.DataSource = ro.ExceptionRules; dgExceptions.DataBind(); }
/// <summary> /// Generate instances for the specified component /// </summary> /// <param name="sender">The sender of the event</param> /// <param name="e">The event parameters</param> protected void btnTest_Click(object sender, EventArgs e) { RecurringObject ro = null; DateTimeInstanceCollection instances; string calendar; int start; double elapsed; DateTime startDate, endDate; try { lblCount.Text = String.Empty; if (!DateTime.TryParse(txtStartDate.Text, CultureInfo.CurrentCulture, DateTimeStyles.None, out startDate) || !DateTime.TryParse(txtEndDate.Text, CultureInfo.CurrentCulture, DateTimeStyles.None, out endDate)) { lblCount.Text = "Invalid start or end date/time format"; return; } // Wrap it in VCALENDAR tags and parse it calendar = String.Format("BEGIN:VCALENDAR\nVERSION:2.0\n{0}\nEND:VCALENDAR", txtCalendar.Text); VCalendar cal = VCalendarParser.ParseFromString(calendar); // Get the first event, to-do, or journal item if (cal.Events.Count > 0) { ro = cal.Events[0]; } else if (cal.ToDos.Count > 0) { ro = cal.ToDos[0]; } else if (cal.Journals.Count > 0) { ro = cal.Journals[0]; } if (ro == null) { lblCount.Text = "No event, to-do, or journal item found"; return; } // Apply the time zone to the calendar. If "None" is selected, the time zone will be cleared on // all items. if (cboTimeZone.SelectedIndex < 1) { cal.ApplyTimeZone(null); } else { cal.ApplyTimeZone(VCalendar.TimeZones[cboTimeZone.SelectedIndex - 1]); } foreach (RRuleProperty rrule in ro.RecurrenceRules) { ApplyLimits(ro, rrule.Recurrence); } foreach (ExRuleProperty exrule in ro.ExceptionRules) { ApplyLimits(ro, exrule.Recurrence); } txtCalendar.Text = ro.ToString(); start = System.Environment.TickCount; instances = ro.InstancesBetween(startDate, endDate, chkInLocalTime.Checked); elapsed = (System.Environment.TickCount - start) / 1000.0; cal.Dispose(); // The date instance contains the start and end date/times, the duration, and time zone // information. The duration is based on the duration of the calendar component. The time zone // information is based on the "In Local Time" parameter of the InstancesBetween() method and // whether or not the component has a Time Zone ID specified. dlDates.DataSource = instances; dlDates.DataBind(); // If nothing was found remind the user that they may need to adjust the start and end date range // to find stuff within the item. if (instances.Count == 0) { lblCount.Text = "Nothing found. If this was unexpected, check the limiting date range " + "in the two date/time text boxes at the top of the form and the calendar item date/time " + "properties to make sure that they do overlap<br/><br/>"; } lblCount.Text += String.Format("Found {0:N0} instances in {1:N2} seconds ({2:N2} instances/second)", instances.Count, elapsed, instances.Count / elapsed); } catch (Exception ex) { lblCount.Text = ex.Message; } }
/// <summary> /// Test the recurrence within the specified iCalendar component /// </summary> /// <param name="sender">The sender of the event</param> /// <param name="e">The event arguments</param> private void btnTest_Click(object sender, EventArgs e) { RecurringObject ro = null; DateTimeInstanceCollection instances; string calendar; int start; double elapsed; try { lblCount.Text = null; // Wrap it in VCALENDAR tags and parse it calendar = String.Format("BEGIN:VCALENDAR\nVERSION:2.0\n{0}\nEND:VCALENDAR", txtCalendar.Text); VCalendar cal = VCalendarParser.ParseFromString(calendar); // Get the first event, to-do, or journal item if (cal.Events.Count > 0) { ro = cal.Events[0]; } else if (cal.ToDos.Count > 0) { ro = cal.ToDos[0]; } else if (cal.Journals.Count > 0) { ro = cal.Journals[0]; } if (ro == null) { lblCount.Text = "No event, to-do, or journal item found"; return; } // Apply the time zone to the calendar. If "None" is selected, the time zone will be cleared on // all items. if (cboTimeZone.SelectedIndex < 1) { cal.ApplyTimeZone(null); } else { cal.ApplyTimeZone(VCalendar.TimeZones[cboTimeZone.SelectedIndex - 1]); } txtCalendar.Text = ro.ToString(); lbDates.Items.Clear(); this.Cursor = Cursors.WaitCursor; start = System.Environment.TickCount; instances = ro.InstancesBetween(dtpStartDate.Value, dtpEndDate.Value, chkInLocalTime.Checked); elapsed = (System.Environment.TickCount - start) / 1000.0; cal.Dispose(); // The date instance contains the start and end date/times, the duration, and time zone // information. The duration is based on the duration of the calendar component. The time // zone information is based on the "In Local Time" parameter of the InstancesBetween() method // and whether or not the component has a Time Zone ID specified. foreach (DateTimeInstance dti in instances) { lbDates.Items.Add(String.Format("{0:G} {1} to {2:G} {3} ({4})", dti.StartDateTime, dti.AbbreviatedStartTimeZoneName, dti.EndDateTime, dti.AbbreviatedEndTimeZoneName, dti.Duration.ToDescription())); if (lbDates.Items.Count > 5000) { lblCount.Text += "A large number of instances were returned. Only the first 5000 " + "have been loaded into the list box.\r\n"; break; } } // If nothing was found remind the user that they may need to adjust the start and end date range // to find stuff within the item. if (instances.Count == 0) { MessageBox.Show("Nothing found. If this was unexpected, check the limiting date range in " + "the two date/time text boxes at the top of the form and the calendar item date/time " + "properties to make sure that they do overlap"); } lblCount.Text += String.Format("Found {0:N0} instances in {1:N2} seconds ({2:N2} instances/second)", instances.Count, elapsed, instances.Count / elapsed); } catch (Exception ex) { MessageBox.Show(ex.ToString()); } finally { this.Cursor = Cursors.Default; } }