Getting Started Using NucliOS IGCalendarView with Xamarin.iOS

Brent Schooley / Wednesday, January 15, 2014

The 13.2 release of NucliOS introduced some new controls for iOS developers. In this post I’m going to focus on the IGCalendarView widget which combines the similar look and feel of the iOS7 calendar with the power and flexibility of Infragistics. This 3 in 1 calendar allows you to navigate between year, month, and day views as well as connect to the events stored on the device. I’ll show you how to use the IGCalendarView with Xamarin.iOS to display the events stored on your iPhone and also show you how to use EventKit to modify events.

nuclios-xamarin-3

Using IGCalendarView with Xamarin.iOS

IGCalendarView is a themeable calendar control that allows you to display both the calendar events on the device as well as custom calendar events you can create in code that do not need to be stored on the device. In this tutorial, we’ll create a single view iPhone application that displays the calendar events that are stored on the device and allow the user to edit them using EventKit. The final application will look like this:

final

Step 1: Creating the project

Start by creating a Single View iPhone application by clicking on “New…” under Solution and configure the project as shown in the following screenshot:

newproject

This will set up a project that uses a single view (i.e. no navigation) which is all we need for this simple sample. A ViewController with a XIB file will be created to represent the view. We won’t need actually customize the XIB file. Since we only need the IGCalendarView, we will add our user interface from code.

Step 2: Adding and configuring the IGCalendarView

The first thing we need to do is add a reference to the IG.dll which is found in /Developer/Infragistics/NucliOS 2013 Volume 2/MonoTouch on your machine. To do this, right-click on References and chose “Edit references…”. Go to the .NET Assembly tab and navigate to the IG.dll as shown here:

references

Now open up the IGCalendarViewXamarinViewController.cs file and add the following using statement:

using Infragistics;  

Add a field for the calendar view:

IGCalendarView _calendar;

Add the following code to the ViewDidLoad override in IGCalendarViewXamarinViewController.cs to initialize an IGCalendarView and add it to the view:

// Create the calendar
_calendar = new IGCalendarView();

// Set the Frame to be the size of the View
_calendar.Frame = this.View.Bounds;

// Set up auto-resizing for rotation purposes
_calendar.AutoresizingMask = UIViewAutoresizing.FlexibleWidth|UIViewAutoresizing.FlexibleHeight;

// Add the calendar to the view
this.View.Add (_calendar);

If you run the application at this point, you should see the following:

statusbar

You probably noticed that the status bar at the top of the screen is overlapping our calendar. This is because of a change in the way the status bar is treated in iOS7. Working around this issue in a way that integrates the status bar is outside of the scope of this tutorial so add the following code to the view controller to hide the status bar:

public override bool PrefersStatusBarHidden ()
{
    return true;
}

You’re free to consider alternative workarounds in your own application.

Step 3: Displaying the device’s calendar events

The calendar is functional as is, but it doesn’t contain any data. Let’s change that by loading up the events from the device. To do this we’ll need to use the EventKit APIs provided by Apple. Xamarin has a very good introduction to EventKit that’s worth reading. Start by adding the following using statements to the top of the view controller file:

using MonoTouch.EventKit;
using MonoTouch.EventKitUI;

We will need a list of NSObjects to manage the data sources for our IGCalendarView so add the following code above the constructor (you’ll need to resolve the reference for System.Collections.Generic as well):

List _dataSources;

Initialize the list in the constructor:

public IGCalendarTestViewController () : base ("IGCalendarTestViewController", null)
{
    _dataSources = new List ();
}

In order to access the calendar objects through EventKit we will need to create an EventStore object that we can access in our app. This object can be expensive to create and teardown so it is recommended that it be created as a long-lived object. This is the perfect scenario for a singleton pattern. Create a new class called App and modify the contents of App.cs to include the following:

using System;
using MonoTouch.EventKit;

namespace IGCalendarViewXamarin
{
    public class App
    {
        public static App Current {
            get { return current; }
        }
        private static App current;

        public EKEventStore EventStore {
            get { return eventStore; }
        }
        protected EKEventStore eventStore;

        static App ()
        {
            current = new App();
        }
        protected App () 
        {
            eventStore = new EKEventStore ( );
        }
    }
}

Now we will be able to access the EventStore at any time in our application by calling App.Current.EventStore.

Next, we need to request permission to access the user’s events. Add the following code just before the calendar view creation code:

var eventStore = App.Current.EventStore;
var accessGranted = await eventStore.RequestAccessAsync(EKEntityType.Event);

Now if we have access we can access the calendars in the event store. For each EKCalendar object we will create an IGCalendarEKDataSourceHelper and add it to our _dataSources array:

if (accessGranted) {
    EKCalendar[] cals = eventStore.GetCalendars (EKEntityType.Event);
    foreach (EKCalendar cal in cals) {
        IGCalendarEKDataSourceHelper ds = new IGCalendarEKDataSourceHelper (cal, App.Current.EventStore);
        _dataSources.Add (ds);
    }
}

Right after the line that sets the AutoresizingMask, add the following line to set the IGCalendarView’s AppointmentDataSources:

_calendar.AppointmentDataSources = _dataSources.ToArray();

Now if you run the code you should be able to see any events that are on the device or simulator. (If you are using the simulator you should launch the Calendar application and add some events to work with in your testing.)

Step 4: Editing an event

Displaying calendar events is great, but what’s even better is responding to taps on those events and allowing the user to edit them! Let’s enable that for our users. To respond to a tap on an event we need to implement a subclass of IGCalendarDelegate and override its AppointmentTapped method. We’ll also pass in an instance of our view controller so that we can present an EKEventEditViewController from within the delegate. To do all of this, add a class called MyCalendarDelegate that extends from IGCalendarViewDelegate. Add the following to the class:

UIViewController _viewController;

public MyCalendarDelegate (UIViewController viewController)
{
    _viewController = viewController;
}

Next, override the AppointmentTapped method and add the following code:

public override void AppointmentTapped (IGCalendarView calView, IGCalendarAppointment appt, IGCalendarAppointmentDataSource dataSource, RectangleF rect, NSDate date)
{
    var ds = dataSource as IGCalendarEKDataSourceHelper;
    var ekEvent = ds.ResolveEventFromAppointment(appt);

    var eventController = new EKEventEditViewController ();
    eventController.EventStore = App.Current.EventStore;
    eventController.Event = ekEvent;
    
    _viewController.PresentViewController (eventController, true, null);
}

This code accesses the EKEvent object for the appointment the user tapped and creates and presents an EKEventEditViewController to display the event. Only thing left to do is handle the event controller’s Completed event and save any edits that the user might have made. Add this code after the “eventController.Event = ekEvent;” line:

eventController.Completed += (sender, e) => {
    switch (e.Action) {
    case EKEventEditViewAction.Canceled:
        break;
    case EKEventEditViewAction.Deleted:
        break;
    case EKEventEditViewAction.Saved:
        NSError err;
        var ev = eventController.Event;

        App.Current.EventStore.SaveEvent (eventController.Event, EKSpan.ThisEvent, out err);

        appt.AllDay = ev.AllDay;
        appt.EndTime = ev.EndDate;
        appt.Location = ev.Location;
        appt.StartTime = ev.StartDate;
        appt.Title = ev.Title;
        break;
    }

    _viewController.UpdateCalendar();
    eventController.DismissViewController(true, null);
};

The key code here is in the case for EKEventEditViewAction.Saved. First we save the event to the EventStore. This updates it in the device calendar. Then we update the IGCalendarView appointment based on the edits to the event. This makes sure the view is in sync with the newly updated calendar appointment.

Back in the IGCalendarViewXamarinViewController’s ViewDidLoad method, set the calendar’s Delegate property:

calendar.Delegate = new MyCalendarDelegate(this);

We also need to add the UpdateCalendar() method to the view controller:

public void UpdateCalendar ()
{
    _calendar.Invalidate ();
}

This causes the calendar to redraw itself to reflect the changes the user made.

And that’s it. The application is ready to go. Run it and you should be able to tap on an event and edit it in the built-in event editor and see the changes reflected on the device.

Summary

This tutorial showed you how to add an IGCalendarView to your iOS application. I also showed you how to use an IGCalendarViewDelegate to handle editing events.

You can download the solution here: IGCalendarViewXamarin.zip

Contact

If you want to comment or reach out to me, the best place to do that is on Twitter @brentschooley. I can also be reached via email at bschooley@infragistics.com.