Random geekery since 2005.

Husband, father, programmer, speaker, writer, blogger, podcaster, collector, traveler, golfer.

31 Days of Mango | Day #9: Calendar API

Written in

by

Day9-CalendarAPIDay8-ContactsAPIDay7-RawCameraDay6-MotionDay5-Gyroscope

This article is Day #9 in a series called 31 Days of Mango.

Today, we’re going to dive back into the Microsoft.Phone.UserData namespace, and look at the other set of data: the calendar.  In this article, we will look at how we can use our user’s calendar data in our applications, and what we’d use it for.

If you would like to try out a sample application on your Windows Phone before going through this article, this application is available in the Windows Phone Marketplace:

DownloadIcon

It’s important to remember that just like the Contact API, this data is read-only.  We won’t be adding new events to the user’s calendar, but we will be able to see when they are available.

Using Windows Phone Calendar Data

One of the most obvious ways we can use this data is for creating a scheduling application.  Imagine you’re building an application for a medical practice, and one of the features is a “schedule an appointment” option.  By grabbing your user’s calendar data and comparing to the available schedules of your doctors, you should be able to easily give the user an appointment option that is ideal for both of you.

[UPDATED: Jamie Thomson brought to my attention that in Mango, you can now see Live Calendars that are shared with you.  Previously, this article stated that there was not an effective way to do this.  Thank you Jamie.]

Building the User Interface

Now that we’ve talked about ways we could use this data in an application, let’s look at how we actually do it.  I prefer to start with the user interface, because it helps me to understand what data I will need/want on my screen.  For the application we will build in this article, we are going to use the DatePicker control from the Silverlight Toolkit for Windows Phone, and show a list of all of the calendar entries the user’s device has for that day.

If you’re not familiar with the Silverlight Toolkit for Windows Phone, prepare to have your mind blown.  It is a free collection of controls that are available on the Codeplex site for building Windows Phone applications.  I discussed it on Day #21 of the 31 Days of Windows Phone, so make sure to check that out before you go much further.  There are some tips about the DatePicker that you don’t want to miss in that article.

Ultimately, our interface is going to be pretty simple.  We will have the DatePicker to allow the user to select a date, and a ListBox that shows the calendar events for that date.  As I mentioned earlier, we can’t create or delete any events with this API, so we’re merely reading and showing the data to the user.

In the XAML below, I’ve used the default Windows Phone Application template again to make it easy to follow along.  The only changes to this interface are the addition of the DatePicker, the ListBox, and a couple of TextBlocks which I will describe after the code.  Please also note the xmlns:toolkit entry for the Silverlight Toolkit for Windows Phone.  You’ll need that to use the DatePicker.

<phone:PhoneApplicationPage
   x:Class="Day9_CalendarAPI.MainPage"
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
   xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
   xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
   xmlns:d="http://schemas.microsoft.com/expression/blend/2008&quot;
   xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006&quot;
    xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit"
   mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
   FontFamily="{StaticResource PhoneFontFamilyNormal}"
   FontSize="{StaticResource PhoneFontSizeNormal}"
   Foreground="{StaticResource PhoneForegroundBrush}"
   SupportedOrientations="Portrait" Orientation="Portrait"
   shell:SystemTray.IsVisible="True">

    <Grid x:Name="LayoutRoot" Background="Transparent">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
            <TextBlock x:Name="ApplicationTitle" Text="31 DAYS OF MANGO – DAY #9" Style="{StaticResource PhoneTextNormalStyle}"/>
            <TextBlock x:Name="PageTitle" Text="calendar api" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
        </StackPanel>

        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            <toolkit:DatePicker x:Name="DateBox" Height="100" Margin="0,37,0,470" ValueChanged="DateBox_ValueChanged" />
            <TextBlock Height="30" HorizontalAlignment="Left" Margin="12,6,0,0" Name="textBlock1" Text="select a date" VerticalAlignment="Top" Width="126" />
            <ListBox x:Name="DateList" Margin="0,143,0,0">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <StackPanel>
                            <TextBlock Text="{Binding StartTime}" FontSize="16" />
                            <TextBlock Text="{Binding Subject}" TextWrapping="NoWrap" FontWeight="Bold" FontSize="24" />
                            <TextBlock Text="{Binding Location}" TextWrapping="NoWrap" Margin="0,0,0,15" FontSize="20" Foreground="Gray"/>
                        </StackPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>
            <TextBlock Height="30" HorizontalAlignment="Left" Margin="70,107,0,0" Name="MessageText" VerticalAlignment="Top" Width="380" TextAlignment="Right" />
        </Grid>
    </Grid>
</phone:PhoneApplicationPage>
 

The DatePicker is a surprisingly self-sufficient control.  It automatically uses today’s date if you don’t provide one (which is perfect for our app), and even has an event for ValueChanged, so that we can perform another calendar search each time the user changes the date value.

The two TextBlocks are really just decoration, but the second one, named MessageText, is used to tell the user how many calendar records we retrieved.  You’ll see that when we get into the code-behind file.

Finally, there’s the ListBox.  This is a slightly more elaborate example than yesterday, but we are binding a DataTemplate of controls to the properties of our Appointment objects that we’ll be getting in our code.  Here’s a quick look at the interface we’re building:

image

Finally, I’ve included a video of the app running on my device.  Check it out to see where this application will finally end up when you’re done with it!

Using the Calendar API

Our example is pretty simple, but we actually end up with a pretty robust interface for our user.  To start, we need to reference the Microsoft.Phone.UserData namespace in our using statements.  After we have that, we need to create a new Appointments object that we will use to access the calendar data on the user’s phone.

Here’s a look at our starter code:

using System;
using System.Linq;
using Microsoft.Phone.Controls;
using Microsoft.Phone.UserData;

namespace Day9_CalendarAPI
{
    public partial class MainPage : PhoneApplicationPage
    {
        Appointments appointments = new Appointments();

        public MainPage()
        {
            InitializeComponent();
            appointments.SearchCompleted += new EventHandler<AppointmentsSearchEventArgs>(appointments_SearchCompleted);
            appointments.SearchAsync(DateBox.Value.Value, DateBox.Value.Value.AddDays(1), null);
        }

        void appointments_SearchCompleted(object sender, AppointmentsSearchEventArgs e)
        {
            //SEARCH THE CALENDAR!
        }
    }
}
 

 

As you can see in the example above, we create a SearchCompleted event handler, and then we call the SearchAsync() method to execute our search.  The SearchAsync takes three parameters:

  • StartDate – a DateTime value that indicates the beginning of our search.  It is an inclusive value, so the time you indicate will also be included in the search.
  • EndDate – another inclusive value, it indicates the end time of our search.
  • State – a user-defined object that you can pass to the search, and it will be returned in the event handler, so that you can identify the individual search.  Simple applications like the one in this article will likely use null for this value.

In our XAML earlier we added a DatePicker to our interface.  You probably noticed that the C# code email above doesn’t really address the user’s selection, nor does it bind the search results to our ListBox control.  Those are the two remaining steps to make our application work like the video from earlier.

For the DatePicker, we need to create an event handler method for the ValueChanged event we created in our XAML.  Because we will likely be calling the SearchAsync() method from several locations in our code, we are just going to have our ValueChanged event method call a new method called SearchCalendar(), where will actually make our SearchAsync() call.  (I removed it from the MainPage() constructor method.)

using System;
using System.Linq;
using Microsoft.Phone.Controls;
using Microsoft.Phone.UserData;

namespace Day9_CalendarAPI
{
    public partial class MainPage : PhoneApplicationPage
    {
        Appointments appointments = new Appointments();

        public MainPage()
        {
            InitializeComponent();
            appointments.SearchCompleted += new EventHandler<AppointmentsSearchEventArgs>(appointments_SearchCompleted);
            SearchCalendar();
        }

        private void SearchCalendar()
        {
            appointments.SearchAsync(DateBox.Value.Value, DateBox.Value.Value.AddDays(1), null);
        }

        private void DateBox_ValueChanged(object sender, DateTimeValueChangedEventArgs e)
        {
            SearchCalendar();
        }

        void appointments_SearchCompleted(object sender, AppointmentsSearchEventArgs e)
        {
            if (e.Results.Count() == 0)
            {
                MessageText.Text = "no events for the selected day";
            }
            else
            {
                MessageText.Text = e.Results.Count() + " events found";
                DateList.ItemsSource = e.Results;
            }
        }
    }
}
 

Finally, you should take a look at the appointments_SearchCompleted() method.  This will get called when our SearchAsync() method completes its search, and contains the data we requested in our search.  In this application, I am checking to see how many records were found, and writing a message to the user in the MessageText textbox.  Finally, if there were records, I am binding the Results of the search to our DateList ListBox that we created in our XAML.

Explaining the Magic of Databinding

For those of you that are getting into XAML development for the first time, the line above:

DateList.ItemsSource = e.Results;

probably seems like there’s some magic going on, and in some ways, there is.  If you look back to our XAML, we had an elaborate ListBox control:

<ListBox x:Name="DateList" Margin="0,143,0,0">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel>
                <TextBlock Text="{Binding StartTime}" FontSize="16" />
                <TextBlock Text="{Binding Subject}" TextWrapping="NoWrap" FontWeight="Bold" FontSize="24" />
                <TextBlock Text="{Binding Location}" TextWrapping="NoWrap" Margin="0,0,0,15" FontSize="20" Foreground="Gray"/>
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>
 

You should notice that I have 3 TextBlock controls defined inside a DataTemplate for the ListBox.  Each of these TextBlocks have a {Binding} statement for their Text values.  What this means to us, as developers, is that we can choose specific properties of our objects, and bind specific XAML elements to their values.

This isn’t limited to text values, either.  You can bind to nearly any property of a XAML element.  Numbers could be used for Opacity values, colors could be used for Foreground and Fill values.  The only real downside to this style of databinding is that if you change the structure of the objects you’re using (let’s say you remove the Subject from the Appointment object), your page will break because it is expecting that value.  In short though, it’s a great way to pass a collection of objects to a ListBox with a minimal amount of code.

Summary

This article walked you through the steps to create an application that reads the user’s calendar data on their device.  As I mentioned earlier, there’s a wide variety of applications that can use this data effectively, from doctor’s offices to synchronization tools.  How will you use this data?

To download a complete working Windows Phone project that uses all of the code from this article, please click the Download Code button below:

download

Tomorrow, we are going to dive into the NetworkInformation class, with an example that will show both the how and the why of this rich piece of data.  See you then!

toolsbutton5

Tags

12 responses to “31 Days of Mango | Day #9: Calendar API”

  1. Ed Dolikian Avatar

    Given that Mango allows for read only access to your calander / contacts, is it somehow possible for both you and others in a workgroup to post info into hotmail or windows live and then have both devices sync to that?

    I’m just getting started w/ Mango but I haven’t had success so far in sync’g my device w/ Outlook the way I used to in WM6.0 using WMDC. I think I had to install/use Outlook connector to load info into my phone but I simply expect that when I make an appointment or update a contact on my device or desktop it automatically sync both ways.

    1. jeffblankenburg Avatar
      jeffblankenburg

      Yes, check out this article on using the Calendar API to create new Windows Live Calendar events. http://isdk.dev.live.com/ISDK.aspx?category=Making+Your+Application+Social&index=0

  2. […] No trackbacks yet. « 31 Days of Mango | Day #9: Calendar API […]

  3. […] 31 Days of Mango | Day #9: Calendar API – Jeff Blankenburg presses on with his series of posts on Windows Phone Mango functionality with a look at the use of the Calendar API in your applicaitons, allowing you to access and display the phone user’s calendar from within your applications. […]

  4. […] 31 Days of Mango | Day #9: Calendar API […]

  5. JT Avatar
    JT

    “But the calendars don’t talk. They don’t synchronize. In fact, the only option we’ve really found is to add both calendars to both phones”

    I might be misundetstaing your point but… I’m pretty sure that any Hotmail calendar can be shared with any other Hotmail user. Actually, more than that, any Hotmail calendar can be shared with anything else that supports iCalendar (e.g. Google Calendar). My wife and I both have our personal calendars on Hotmail and I can visit calendar.live.com, log in as me, and see my wife’s calendar alongside my own.

    Have I misunderstood? Apologies if so.

    1. jeffblankenburg Avatar
      jeffblankenburg

      Yes, in the web interface, you can see both calendars. But on Windows Phone, if you only add your own Live ID, you won’t see the other shared calendars. You need to specifically add the other user’s calendar to your phone as well, which is what I described.

      1. JT Avatar
        JT

        Sorry Jeff, I beg to differ 🙂 I have only added my Live ID to the phone and I can see my wife’s calendar too. You have to go into Calendar->Settings to toggle their being displayed, but they ARE there.

        (N.B. This only works if you have upgraded to Mango but this is 31 days of Mango so I took that as a given…)

  6. Jorge Levy Avatar

    I have several calendar on my device (my live account, birthdays, facebook, even a gmail calendar), and I could find that some of them mark the appointments as private, and those have the properties Subject and Location as ‘Could not evaluate expression’. For this I tried the following code:

    void appointments_SearchCompleted(object sender, AppointmentsSearchEventArgs e)
    {
    var events = e.Results.Where(ev => !ev.IsPrivate);
    if (events.Count() == 0)
    {
    MessageText.Text = “no events for the selected day”;
    }
    else
    {
    MessageText.Text = events.Count() + ” events found”;
    DateList.ItemsSource = events;
    }
    }

  7. […] Este artículo es una traducción de Day 9: Calendar API, puedes encontrarlo aquí en la versión or… […]

  8. […] Англоязычная версия статьи доступна здесь. […]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Create a website or blog at WordPress.com

%d bloggers like this: