This is a migrated thread and some comments may be shown as answers.

How to enhance limited iCalendar support

7 Answers 164 Views
Scheduler and Reminder
This is a migrated thread and some comments may be shown as answers.
Tinus
Top achievements
Rank 2
Tinus asked on 05 Aug 2010, 09:52 AM
Hello,

in my app I have to import and export iCalendar data. I do not use data binding. iCalendar format is used to persist data.

Unfortunately the existing implementation is limited.Only a subset of the appointment properties are exported. For example resources are completely missing. Is there an "easy" way to add resources for import/export?

A second problem is double import creating double entries instead of overwriting. Every VEVENT has a uid property which uniquely identifies the event. This should not create duplicates on import.

Regards
Martin

7 Answers, 1 is accepted

Sort by
0
Dobry Zranchev
Telerik team
answered on 06 Aug 2010, 03:57 PM
Hi Tinus,

Thank you for writing.

1. Unfortunately, for now we do not support exporting of the resources in ICal format. We will research how we can represent in this format. You are the first to ask for this, and if more people ask for this feature we will implement it. Meanwhile, we support custom import/export. You could implement your own classes that store and load appointments to a custom format. The help is missing here, but I will prepare an example for one of next two official releases.

2. We do not support the functionality to verify whether the item is already imported. You could remove all appointments and import the file that you want.

Feel free to write us if you have other questions.

Greetings,
Dobry Zranchev
the Telerik team
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
0
Tinus
Top achievements
Rank 2
answered on 06 Aug 2010, 04:22 PM
Hi Dobry,

thanks for your feedback.

1. I can't wait for one of next two official releases. I will have a look at the source code and try to derive  from SchedulerICalendarExporter/Importer. Maybe I can add resource support this way.

2. Removing all appointments during import is no solution because this would prohibit to import from different sources and create a merged schedule.

Regards
Martin
0
Peter
Telerik team
answered on 11 Aug 2010, 07:36 PM
Hello Tinus,

Thank you for writing.

You are able to inherit SchedulerICalendarExporter and implement custom logic in the WriteAdditionalDataForAppointment. Regarding your second question, you should take a look on VEVENT's Equals(CalObject other) function (or HasSameProperties function) which compares two CalObject objects.

Let me know whether this helps.

All the best,
Peter
the Telerik team
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
0
Tinus
Top achievements
Rank 2
answered on 17 Aug 2010, 11:37 AM
Hi Peter,

thanks for the hints, will keep you informed.

Martin
0
Tinus
Top achievements
Rank 2
answered on 16 Sep 2010, 08:47 AM
ok, back from vacation here's my solution (I've uploaded the 2 files to code library).

To export resources derive a new class from SchedulerICalendarExporter and override WriteAdditionalDataForAppointment.
We need access to the resource collection of RadScheduler, so I added a new constructor:

      private readonly SchedulerResourceCollection m_Resources;

      public SchedulerICalendarExporter2(SchedulerResourceCollection resources)
         : base()
      {
         m_Resources = resources;
      }

WriteAdditionalDataForAppointment now first calls the base class and then checks for a ResourceId. When present, a resoure string is created and added to the properties collection:

      protected override void WriteAdditionalDataForAppointment(IEvent appointment, CalObject calObject)
      {
         base.WriteAdditionalDataForAppointment(appointment, calObject);

         // new);
         if (appointment.ResourceId != null)
         {
            string resources = BuildResources(appointment.ResourceIds);
            calObject.AddProperty("RESOURCES", resources);
         }
      }

      private string BuildResources(ObservableCollection<EventId> resourceIds)
      {
         string res = string.Empty;

         foreach (EventId resourceId in resourceIds)
         {
            string resource = m_Resources.GetById(resourceId.KeyValue).Name;
            if (res == string.Empty)
               res += resource;
            else
            {
               res += "," + resource;
            }
         }

         return res;
      }

To use the new export create an instance of the new export and use the constructor to assign the resource collection.

         ISchedulerExporter exporter = new SchedulerICalendarExporter2(radScheduler1.Resources);
        using (FileStream f = new FileStream("export.ics"FileMode.Create))
         {
            radScheduler1.Export(f, exporter);
         }

Importing resources from iCal is done in a very similar way. Again we derive from SchedulerICalendarImporter and need a constructor which provides the resource collection:

      private SchedulerResourceCollection m_Resources;

      public SchedulerICalendarImporter2(SchedulerResourceCollection resources)
         : base()
      {
         m_Resources = resources;
      }

Here we override ApplyAdditionalData and add back our resoure Ids.

      protected override void ApplyAdditionalData(IEvent appointment, CalObject calObject)
      {
         base.ApplyAdditionalData(appointment, calObject);

         CalProperty prop = calObject["RESOURCES"];
         if (prop != null)
         {
            AddResourceIds(prop, appointment);
         }
      }

      private void AddResourceIds(CalProperty prop, IEvent appointment)
      {
         string[] resources = CalProperty.ToText(prop).Split(new[] { ';'',' }, StringSplitOptions.RemoveEmptyEntries);

         foreach (string resource in resources)
         {
            if (m_Resources.GetById(resource) == null)
               m_Resources.Add(new Resource(resourceresource));
            appointment.ResourceIds.Add(new EventId(resource));
         }
      }

And finally I solved my duplication problem by multiple imports. Override GetAppointments and rebuild the collection after creating a unique dictionary:

      /// <summary>
      /// Remove duplicates based on UniqueId
      /// </summary>
      /// <exception cref="CalendarParseException"><c>CalendarParseException</c>.</exception>
      protected override void GetAppointments(CalObject calendar, ICollection<IEvent> collection)
      {
         base.GetAppointments(calendar, collection);

         Dictionary<EventIdIEvent> dictionary = new Dictionary<EventIdIEvent>();
         foreach (IEvent ievent in collection)
         {
            dictionary[ievent.UniqueId] = ievent;
         }

         collection.Clear();
         foreach (IEvent iEvent in dictionary.Values)
            collection.Add(iEvent);
      }

Regards
Martin
0
Stefan
Telerik team
answered on 21 Sep 2010, 01:53 PM
Hello Tinus,

Please find the full code library here: Import and export iCalendar data with resources

Best wishes,
Stefan
the Telerik team
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
0
jdgoulden
Top achievements
Rank 1
answered on 15 Oct 2010, 05:26 PM
Thank you for the code example, this was exactly what I was looking to do as well
Tags
Scheduler and Reminder
Asked by
Tinus
Top achievements
Rank 2
Answers by
Dobry Zranchev
Telerik team
Tinus
Top achievements
Rank 2
Peter
Telerik team
Stefan
Telerik team
jdgoulden
Top achievements
Rank 1
Share this question
or