Skip to main content
March 13, 2014
PC

Build apps that connect with People and Calendar, Part 2: Appointments



In the first post of this series, we looked at one of the contracts introduced with Windows 8.1, contact cards. In this post we’ll explore how an app can work with the user’s calendar through the Windows 8.1 Appointments API, where calendar actions are handled by the user’s chosen calendar app.

Integrating apps with appointments

We all have appointments in our calendar, and use it as the “the source” to inform us what we have going on for the day, the week or even next couple months. But we also use many other apps that have events and appointments.

There are Facebook events, party invitations in Evite, recurring book club meetings in Meetup, due dates for classroom work and assignments in a studies app, flight bookings in a travel app, restaurant reservations, birthday and anniversary dates, and so on. Some of these could be your apps already in the Windows Store or you are a developer thinking about creating such an app.

If each app has its own calendaring solution, the distribution of data makes it hard for the user to answer a seemingly simple question such as “what things do I have going on today?” We all expect our calendar to be the single place for us to see everything on our schedule. We’ve seen the convenient “Add to Calendar” button on many of the websites, why should we not have the same for the apps we like to use? With the Windows 8.1 Appointments contract you can! Your Windows 8.1 apps can let your users easily view their schedule in their calendar, and also add events to their preferred calendar–all right from your app!

What is the Appointments contract?

Similar to other contracts in Windows, like Share and People picker, the appointments contract is also a contract between the source app (app that has appointment and events info) and the target app (user’s preferred calendar supporting the provider contract). The contract enables the following scenarios:

  1. View the user’s calendar alongside the source app.
  2. Add new appointments to the user’s calendar.
  3. Replace an existing appointment in the user’s calendar.
  4. Remove an existing appointment from the user’s calendar.

The APIs for this are found in the Windows.ApplicationModel.Appointments namespace, specifically the AppointmentManager class.

Viewing the calendar from your app

To view the user’s calendar, call the AppointmentManager.ShowTimeFrameAsync method from your app, passing two arguments:

  • A date and time object that specifies the start of the timeframe to the target calendar app.
  • A timespan that hints to the calendar app to the appropriate day, week or month view with which the calendar app is launched. (The timespan is expressed in 100ns units in C#, Visual Basic, and C++; in JavaScript you use milliseconds).

With this information, the user’s default calendar app is launched alongside your app (Figure 1). From here, the user can interact with the fully immersive calendar, resize, or swipe it away.

Figure 1

Figure 1

JavaScript

// Show the appointment provider app at the current date and time
// with a 1 hour duration

function showTimeFrame() {
var dateToShow = new Date();
Windows.ApplicationModel.Appointments.AppointmentManager.showTimeFrameAsync(
dateToShow, (60 * 60 * 1000));
}

C#

/// Show the default appointment provider to 2/25/2014 at 6:32:00pm Pacific Time
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>

private async void Show_Click(object sender, RoutedEventArgs e)
{
var dateToShow = new DateTimeOffset(2014, 2, 25, 18, 32, 0, 0,
TimeSpan.FromHours(-8));
var duration = TimeSpan.FromHours(1);
await Windows.ApplicationModel.Appointments.AppointmentManager.ShowTimeFrameAsync(
dateToShow, duration);
}

Adding an event from your app to the calendar

To add a new appointment, call the AppointmentManager.ShowAddAppointmentAsync method with the following arguments:

  • An Appointment object representing the information for the event to be added.
  • A rectangle for the area of the app’s UI that’s invoking the calendar. For example, if an app uses a button to provide the option to “Add to Calendar”, then provide the coordinates of the button so the calendar app’s UI displays around the button, not overlapping it.
  • (Optional) Preferred placement of the calendar app’s UI relative to the selection area. Options are above (default), below, left or right of the user selection area.

The method invokes the calendar app’s UI in a flyout that is overlaid on your app to provide an inline experience (Figure 2). It allows the user to verify the appointment information prior to adding it to their calendar, which also serves as a safeguard against apps that would try to spam the calendar. The calendar flyout consists of a Windows-provided header showing the calendar app’s title and logo and a body in which the calendar app renders its UI. This provides a consistent experience for the user, because adding an appointment from any source app will always show this familiar and easily recognizable UI. In return, the source app gets a unique identifier for the event that was added to the calendar, which can be used to invoke a similar workflow to replace or remove existing events. The calendar app shows the appropriate UI based on the specific action, of course.

Figure 2

Figure 2

JavaScript


function addAppointment(e) {
// Create an Appointment that should be added the user's
// appointments provider app.
var appointment = new Windows.ApplicationModel.Appointments.Appointment();

appointment.startTime = new Date(2014, 2, 28, 18); // March 28th, 2014 at 6:00pm
appointment.duration = (60 * 60 * 100000) / 100; // 1 hour in 100ms units
appointment.location = "Ben Miller's home";
appointment.subject = "Frank's Birthday";
appointment.details = "Surprise party to celebrate Frank's 60th birthday! Hoping you all can join us.";
appointment.reminder = (15 * 60 * 1000000000) / 100; // Remind me 15 minutes prior to appointment

// Get the selection rect of the button pressed to add this appointment
var boundingRect = e.srcElement.getBoundingClientRect();
var selectionRect = { x: boundingRect.left, y: boundingRect.top,
width: boundingRect.width, height: boundingRect.height };

// ShowAddAppointmentAsync returns an appointment id if the appointment given was added to the user's calendar.
// This value should be stored in app data and roamed so that the appointment can be replaced or removed in the future.
// An empty string return value indicates that the user canceled the operation before the appointment was added.
Windows.ApplicationModel.Appointments.AppointmentManager.showAddAppointmentAsync(
appointment, selectionRect, Windows.UI.Popups.Placement.default)
.done(function (appointmentId) {
if (appointmentId) {
document.querySelector('#result').innerText =
"Appointment Id: " + appointmentId;
} else {
document.querySelector('#result').innerText = "Appointment not added";
}
});
}

C#

/// <summary>
/// Creates an Appointment based on the input fields and validates it.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void CreateAppointment(object sender, RoutedEventArgs e)
{
var appointment = new Windows.ApplicationModel.Appointments.Appointment();

// StartTime
var date = StartTimeDatePicker.Date;
var time = StartTimeTimePicker.Time;
var timeZoneOffset = TimeZoneInfo.Local.GetUtcOffset(DateTime.Now);
var startTime = new DateTimeOffset(date.Year, date.Month, date.Day, time.Hours,
time.Minutes, 0, timeZoneOffset);
appointment.StartTime = startTime;

// Subject
appointment.Subject = SubjectTextBox.Text;

// Location
appointment.Location = LocationTextBox.Text;

// Details
appointment.Details = DetailsTextBox.Text;

// 1 hour duration is selected
appointment.Duration = TimeSpan.FromHours(1);

// Reminder
appointment.Reminder = TimeSpan.FromMinutes(15);
}

/// <summary>
/// Adds an appointment to the default appointment provider app.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private async void AddAppointment(object sender, RoutedEventArgs e)
{
// Create an Appointment that should be added the user's appointments
// provider app.
var appointment = new Windows.ApplicationModel.Appointments.Appointment();

// Get the selection rect of the button pressed to add this appointment
var rect = GetElementRect(sender as FrameworkElement);

// ShowAddAppointmentAsync returns an appointment id if the appointment given was added to the user's calendar.
// This value should be stored in app data and roamed so that the appointment can be replaced or removed in the future.
// An empty string return value indicates that the user canceled the operation before the appointment was added.
String appointmentId = await
Windows.ApplicationModel.Appointments.AppointmentManager.ShowAddAppointmentAsync(
appointment, rect, Windows.UI.Popups.Placement.Default);
if (appointmentId != String.Empty)
{
ResultTextBlock.Text = "Appointment Id: " + appointmentId;
}
else
{
ResultTextBlock.Text = "Appointment not added.";
}
}

As you can see, the source app and appointment provider app collaborate through a strongly typed Appointment object. This object supports a rich set of properties such as recurrence to allow adding recurring events to a user’s calendar, invitees to be able to provide a list of participants for the appointment, and so on.

Apps can also offer the functionality to replace or remove an existing appointment added to the user’s calendar. To replace an appointment, call AppointmentManager.ShowReplaceAppointmentAsync with the updated appointment details and an appointment identifier for the appointment to be replaced. If a matching appointment is not found because the user may have deleted it from their calendar, a new appointment is added and a unique identifier for the replaced appointment is returned to your app.

To delete an existing appointment, call AppointmentManager.ShowRemoveAppointmentAsync API with an appointment identifier for the appointment to be removed. If a matching appointment is found in the user’s calendar, the calendar app’s UI is displayed in a flyout to let the user verify the appointment being removed and confirm its removal. This method returns a Boolean value indicating whether the Appointment provider app removed the appointment.

For further details on all of the above methods, please refer to the Appointments API sample.

Appointment Provider Apps

The built-in Windows Calendar app already supports the appointment provider contract as a target, but it is also possible for other apps to serve this role through the contract.

To become an appointment provider app, you first need to update your app’s manifest to include the AppointmentsProvider extension, which lets Windows know that your app is capable of managing appointments. Next, your app must handle each of the actions an appointments provider can perform for other apps. These actions include adding, removing, and replacing an appointment, and showing a time frame, the latter of which is basically just activating the appointments provider app to show the user’s calendar at a particular date and time. For more details on how to become an appointment provider app, see this MSDN blog post from Nick Eubanks.

In conclusion

User’s love apps that allow them to complete tasks quickly without switching context. With the Appointment APIs, apps can let users quickly view their calendar availability and add or update events to their preferred calendar, so they can have an aggregated view of everything that is going on in their day. The user is always in control of what gets into their calendar by showing the calendar app’s UI in a flyout overlaid in your app. The built-in Windows Calendar app already supports the appointment provider contract to work with your apps. We hope to see many apps leverage this new contract to provide more tailored and personalized experiences for their users.

Zainab Hakim, Senior Program Manager, Windows Developer Platform