Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

31 Days of Mango | Day #9: Calendar API

DZone's Guide to

31 Days of Mango | Day #9: Calendar API

· Mobile Zone
Free Resource

Download this comprehensive Mobile Testing Reference Guide to help prioritize which mobile devices and OSs to test against, brought to you in partnership with Sauce Labs.

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

Day9-CalendarAPI

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.

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.

Another great example of this would be calendar synchronization.  For example, my wife and I each have a Windows Phone, and we each use our Hotmail calendar for our events.  With two children, you can imagine there’s a great deal of juggling that goes on to make sure everyone gets where they need to be.  Most of the kids’ activities are scheduled by my wife, and she puts them on her calendar.  My calendar is mostly focused on my work travel, user group meetings, and sports that I play.  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.  This way, I don’t schedule a trip during an important family event, and she doesn’t schedule events when I’ll be out of town.  An application that would take the two calendars and synchronize them would be an amazing addition to my device.

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"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   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"
   xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    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


Source: http://www.jeffblankenburg.com/2011/11/09/31-days-of-mango-day-9-calendar-api/

Analysts agree that a mix of emulators/simulators and real devices are necessary to optimize your mobile app testing - learn more in this white paper, brought to you in partnership with Sauce Labs.

Topics:

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}