Quickstart: Reading data from app calendars (XAML)

[This article is for Windows 8.x and Windows Phone 8.x developers writing Windows Runtime apps. If you’re developing for Windows 10, see the latest documentation]

Windows Phone Store apps can use the APIs in the Windows.ApplicationModel.Appointments namespace to read data from all calendars on the device, including calendars created and managed by other apps, if they allow it. This feature enables your app to provide a different view into the user's calendars than the built-in Calendar app on the device.

Here, we'll show you how to show a list of the calendars on the device, how to retrieve upcoming appointments, and how to show appointment details.

Prerequisites

  • We recommend that you be familiar with Microsoft Visual Studio and its associated templates.
  • We recommend that you be familiar with C# development.

Add the Appointment capability to your app manifest

Before you can use any of the app calendar APIs you need to update your app manifest. In Solution Explorer, double-click Package.appxmanfest to open the manifest designer. On the Capabilities tab, check the Appointments capability.

Get an instance of the AppointmentStore object

You get access to the device's calendars through the AppointmentStore class. Get an instance of this object by calling RequestStoreAsync, using the value AllCalendarsReadOnly to indicate that you want read access to all of the device's calendars. It's a good idea to save the appointment store to a class variable, because you will need it for other app calendar operations.

protected async override void OnNavigatedTo(NavigationEventArgs e)
{
    appointmentStore = await AppointmentManager.RequestStoreAsync(AppointmentStoreAccessType.AllCalendarsReadOnly);
}

List all calendars on the device

Get a list of all of the calendars on the device by calling FindAppointmentCalendarsAsync. The IncludeHidden option will include calendars in the result that are not displayed by the device's built-in calendar app. But keep in mind that app's can configure their calendar to be readable only by the system, in which case the calendar will not show up in the returned list. If you are going to show the calendar name in your UI, such as binding the list to a ListBox as this example does, use the DisplayName property to show the title of the calendar.

public async void ShowCalendars(bool onlyShowVisible)
{
    if (onlyShowVisible)
    {
        calendars = await appointmentStore.FindAppointmentCalendarsAsync();
    }
    else
    {
        calendars = await appointmentStore.FindAppointmentCalendarsAsync(FindAppointmentCalendarsOptions.IncludeHidden);
    }

    AppointmentCalendarListBox.ItemsSource = calendars;
}

Show all upcoming appointments on the device

Get a list of upcoming appointments by calling FindAppointmentsAsync, specifying a start date and a time span that define the range of dates for which appointments will be returned. To improve performance, a limited set of fields are populated with data by default. If you want the returned appointments to have data for specific fields, specify the fields you want with the FindAppointmentsOptions class. The MaxCount property sets the maximum number of appointments you want to be returned.

public async void ShowUpcomingAppointments(int days, int max)
{
    FindAppointmentsOptions findOptions = new FindAppointmentsOptions();
    findOptions.MaxCount = 3;
    findOptions.FetchProperties.Add(AppointmentProperties.Subject);
    findOptions.FetchProperties.Add(AppointmentProperties.Location);

    IReadOnlyList<Appointment> appointments = 
        await appointmentStore.FindAppointmentsAsync(DateTime.Now, TimeSpan.FromDays(days), findOptions);

    AppointmentListBox.ItemsSource = appointments;

    AppointmentListBox.SelectionChanged += AppointmentListBox_SelectionChanged;
}
void AppointmentListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    if (AppointmentListBox.SelectedItem != null)
    {
        Appointment appt = AppointmentListBox.SelectedItem as Appointment;
        ShowAppoinmentDetails(appt.LocalId);
    }
}

Show today's appointments

This example shows how to get the appointments for a single day.

async public void GetDayView()
{
    var start = DateTime.Today;

    //note TimeSpan.FromDays(1) will not work because of Daylight Savings Time
    var duration = new DateTimeOffset(start.AddDays(1)) - new DateTimeOffset(start);

    var daysAppointments = await appointmentStore.FindAppointmentsAsync(start, duration);

    AppointmentListBox.ItemsSource = daysAppointments;
}

Retrieve an appointment and expand recurrence

You retrieve a single appointment by calling GetAppointmentAsync and passing in the LocalId of the appointment. If an appointment has a non-null Recurrence property, that means it is a recurring appointment. To get all of the instances of a recurring appointment, first you retrieve the calendar that the appointment belongs to by calling GetAppointmentCalendarAsync. Then you call FindAllInstancesAsync, specifying the ID of the master appointment, a date range, and an optional FindAppointmentsOptions if you want to specify the fields that you want to be populated with data.

private async void ShowAppoinmentDetails(string localAppointmentId)
{
    currentAppointment = await appointmentStore.GetAppointmentAsync(localAppointmentId);

    if (currentAppointment.Recurrence != null && expandRecurrence)
    {
        AppointmentCalendar calendar =
            await appointmentStore.GetAppointmentCalendarAsync(currentAppointment.CalendarId);

        FindAppointmentsOptions options = new FindAppointmentsOptions();
        options.MaxCount = 10;

        IReadOnlyList<Appointment> appointmentInstances = await
            calendar.FindAllInstancesAsync(
                localAppointmentId,
                DateTime.Today,
                TimeSpan.FromDays(365),
                options);

        RecurrenceListBox.ItemsSource = appointmentInstances;
    }
}

Show appointment conflicts

You can find out if an appointment conflicts with other appointments on the device by calling FindConflictAsync. If there is a conflict, call ShowTimeFrameAsync to launch the default appointment provider and allow the user to view the conflict.

private async void ShowConflicts_Click(object sender, RoutedEventArgs e)
{
    if (currentAppointment != null)
    {
        AppointmentConflictResult conflict =
            await appointmentStore.FindConflictAsync(currentAppointment);

        if (conflict.Type != AppointmentConflictType.None)
        {
            await AppointmentManager.ShowTimeFrameAsync(
                conflict.Date,
                new TimeSpan(0));
        }
    }
}

Launching the built-in calendar UI

You can launch the built-in calendar UI to allow the user to add, remove, or replace an app calendar appointment. With these APIs, you pass in the LocalId of the appointment you are operating on. These APIs have a Rect argument to be consistent with Windows APIs that use this argument for placing the built-in UI. The calendar UI takes up the entire screen on Windows Phone and so these arguments are ignored by the system.

private async void AddButton_Click(object sender, RoutedEventArgs e)
{
    var appointment = new Appointment();
    await appointmentStore.ShowAddAppointmentAsync(appointment, new Rect());
}

private async void RemoveButton_Click(object sender, RoutedEventArgs e)
{
    var appointment = appointmentListBox.SelectedItem as Appointment;
    await appointmentStore.ShowRemoveAppointmentAsync(appointment.LocalId, new Rect());
}

private async void ReplaceButton_Click(object sender, RoutedEventArgs e)
{
    var oldAppointment = appointmentListBox.SelectedItem as Appointment;
    var newAppointment = new Appointment();
    await appointmentStore.ShowReplaceAppointmentAsync(oldAppointment.LocalId, newAppointment, new Rect());
}

Summary and next steps

Now you have a basic understanding of how to read data from app calendars.