Win 8.1で追加された新しいコントラクトを利用すると、カレンダーアプリに予定を入れられる。カレンダーへの予定追加と更新の方法を説明する。
powered by Insider.NET
カレンダーアプリに予定を入れたいと思ったことはないだろうか? 例えば、イベントの予約をするアプリで、予約の完了と同時にそのイベントの予定をカレンダーに入れたいといった場合だ。Windows 8.1(以降、Win 8.1)で追加された新しいコントラクトを利用すると、それが可能になる。本稿では、新しいコントラクトを紹介した後、新しい予定を作ってカレンダーに入れ、またそれを更新する方法を解説する。なお、本稿のサンプルは「Windows Store app samples:MetroTips #66(Windows 8.1版)」からダウンロードできる。
Win 8.1用のWindowsストアアプリを開発するには、Win 8.1とVisual Studio 2013(以降、VS 2013)が必要である。本稿ではOracle VM VirtualBox上で64bit版Windows 8.1 Pro(日本語版)とVisual Studio Express 2013 for Windows(日本語版)*1を使用している。
*1 マイクロソフト公式ダウンロードセンターの「Microsoft Visual Studio Express 2013 for Windows」から無償で入手できる。
共有やファイルピッカーなどのコントラクトは、すでにおなじみだろう。Win 8.1では、予定(Appointment)と連絡先(Contact)のコントラクトが新しく追加された(次の画像)。カレンダーアプリに予定を入れるには、予定コントラクトを用いる。
予定を管理するアプリ(=カレンダーアプリ)は「予定プロバイダー」と呼ばれ、連絡先を管理するアプリは「連絡先プロバイダー」と呼ばれる。これらのプロバイダーアプリを作るには、マニフェストで「デバイス機能」の宣言が必要になる(VS 2013のGUIからは設定できない)。カレンダーアプリに予定を入れる側のアプリには、宣言は不要だ。
さて、本稿では予定のコントラクトを利用する。予定プロバイダーは、Win 8.1に標準の「カレンダー」アプリが実装している。予定のコントラクトと予定プロバイダーを使うと、予定の追加、置き換え、そして予定の表示(正確には、予定が入っている付近の日時の表示)が可能だ。次の画像の左半分は本稿のために作成したアプリで、予定をカレンダーアプリに追加しようとしているところ。右半分はカレンダーアプリで、追加された予定の辺りのカレンダーを表示しているところである。
本稿ではXAMLコードの解説はしないので、次の図を参考にして適宜UIを作成してほしい。なお、TextBoxコントロール(Windows.UI.Xaml.Controls名前空間)に指定してあるMaxLengthプロパティの値は、予定プロバイダーが受け取り可能な最大長である。
予定を表すAppointmentオブジェクト(Windows.ApplicationModel.Appointments名前空間)を作り、AppointmentManagerクラス(Windows.ApplicationModel.Appointments名前空間)のShowAddAppointmentAsyncメソッドを呼び出せばよい。ただし、ShowAddAppointmentAsyncメソッドを呼び出すときに、フライアウトを表示する基準位置を指定する必要がある。
まず、予定を表すAppointmentオブジェクトは、次に示すメソッドのようにして作成する。
private Windows.ApplicationModel.Appointments.Appointment CreateAppointment()
{
var appointment = new Windows.ApplicationModel.Appointments.Appointment();
// 件名
appointment.Subject = subjectTextBox.Text;
// 開始日時
DateTimeOffset date = datePicker1.Date;
TimeSpan start = timePicker1.Time;
appointment.StartTime = date.Add(start);
// 継続時間
TimeSpan end = timePicker2.Time;
appointment.Duration = end.Subtract(start);
// 場所
appointment.Location = locationTextBox.Text;
// 詳細
appointment.Details = detailsTextBox.Text;
return appointment;
}
Private Function CreateAppointment() _
As Windows.ApplicationModel.Appointments.Appointment
Dim appointment = New Windows.ApplicationModel.Appointments.Appointment()
' 件名
appointment.Subject = subjectTextBox.Text
' 開始日時
Dim appointmentDate As DateTimeOffset = datePicker1.Date
Dim start As TimeSpan = timePicker1.Time
appointment.StartTime = appointmentDate.Add(start)
' 継続時間
Dim endTime As TimeSpan = timePicker2.Time
appointment.Duration = endTime.Subtract(start)
' 場所
appointment.Location = locationTextBox.Text
' 詳細
appointment.Details = detailsTextBox.Text
Return appointment
End Function
次に、フライアウトを表示する基準位置は、タップされたボタンにしよう。ボタンなどのFrameworkElementオブジェクト(Windows.UI.Xaml名前空間)の位置とサイズを取得するコードは次のメソッドのように書ける。
private Windows.Foundation.Rect GetElementRect(FrameworkElement element)
{
var buttonTransform = element.TransformToVisual(null);
var point = buttonTransform.TransformPoint(new Windows.Foundation.Point());
var size = new Windows.Foundation.Size(element.ActualWidth, element.ActualHeight);
return new Windows.Foundation.Rect(point, size);
}
Private Function GetElementRect(element As FrameworkElement) _
As Windows.Foundation.Rect
Dim buttonTransform = element.TransformToVisual(Nothing)
Dim point = buttonTransform.TransformPoint(New Windows.Foundation.Point())
Dim size = New Windows.Foundation.Size(element.ActualWidth, element.ActualHeight)
Return New Windows.Foundation.Rect(point, size)
End Function
最後に、ShowAddAppointmentAsyncメソッドの呼び出しを合わせて、ボタンのクリックイベントにまとめる(次のコード)。
private async void registerButton_Click(object sender, RoutedEventArgs e)
{
// 予定のオブジェクトを作る
var appointment = CreateAppointment();
// フライアウトを表示するターゲット(=ボタン)の位置とサイズ
var rect = GetElementRect(sender as FrameworkElement);
// 予定を登録するフライアウトを出す
var appointmentId
= await Windows.ApplicationModel.Appointments.AppointmentManager
.ShowAddAppointmentAsync(appointment, rect,
Windows.UI.Popups.Placement.Default);
}
Private Async Sub registerButton_Click(sender As Object, e As RoutedEventArgs)
' 予定のオブジェクトを作る
Dim appointment = CreateAppointment()
' フライアウトを表示するターゲット(=ボタン)の位置とサイズ
Dim rect = GetElementRect(sender)
' 予定を登録するフライアウトを出す
Dim appointmentId _
= Await Windows.ApplicationModel.Appointments.AppointmentManager _
.ShowAddAppointmentAsync(appointment, rect, _
Windows.UI.Popups.Placement.Default)
End Sub
ここで注意すべきは、ShowAddAppointmentAsyncメソッドを呼び出しても、予定はカレンダーに登録されず、予定をカレンダーアプリに登録するためのフライアウトが表示されるだけであることだ。フライアウトの下部にある[追加]ボタンをエンドユーザーがタップしたときに、実際にカレンダーアプリに予定が追加されるのである。そして、カレンダーアプリが予定の追加に成功すると、1文字以上の文字列(「予定ID」)がShowAddAppointmentAsyncメソッドから返ってくる。エンドユーザーが[追加]ボタンをタップせずにフライアウトを閉じたり、タップしてもカレンダーアプリ側で予定の追加に失敗したりすると、空文字列(=String.Empty)が返される。
AppointmentManagerクラスのShowTimeFrameAsyncメソッドを呼び出せばよい(次のコード)。それだけで、カレンダーアプリが起動して、指定日時前後のカレンダーが表示される。横置き画面の場合は、先に載せた画像のように自動的に画面が分割され、呼び出し元のアプリとカレンダーアプリが並んで表示される。
private async void registerButton_Click(object sender, RoutedEventArgs e)
{
// 予定のオブジェクトを作る
var appointment = CreateAppointment();
// フライアウトを表示するターゲット(=ボタン)の位置とサイズ
var rect = GetElementRect(sender as FrameworkElement);
// 予定を登録するフライアウトを出す
var appointmentId
= await Windows.ApplicationModel.Appointments.AppointmentManager
.ShowAddAppointmentAsync(appointment, rect,
Windows.UI.Popups.Placement.Default);
if (!string.IsNullOrEmpty(appointmentId)) // 予定の登録に成功した場合
{
// カレンダーアプリを表示する
var timeToShow = appointment.StartTime; // 表示させたい日時
var duration = TimeSpan.FromDays(1.0); // 表示させたい時間範囲の目安
await Windows.ApplicationModel.Appointments.AppointmentManager
.ShowTimeFrameAsync(timeToShow, duration);
}
}
Private Async Sub registerButton_Click(sender As Object, e As RoutedEventArgs)
' 予定のオブジェクトを作る
Dim appointment = CreateAppointment()
' フライアウトを表示するターゲット(=ボタン)の位置とサイズ
Dim rect = GetElementRect(sender)
' 予定を登録するフライアウトを出す
Dim appointmentId _
= Await Windows.ApplicationModel.Appointments.AppointmentManager _
.ShowAddAppointmentAsync(appointment, rect, _
Windows.UI.Popups.Placement.Default)
If (Not String.IsNullOrEmpty(appointmentId)) Then ' 予定の登録に成功した場合
' カレンダーアプリを表示する
Dim timeToShow = appointment.StartTime ' 表示させたい日時
Dim duration = TimeSpan.FromDays(1.0) ' 表示させたい時間範囲の目安
Await Windows.ApplicationModel.Appointments.AppointmentManager _
.ShowTimeFrameAsync(timeToShow, duration)
End If
End Sub
AppointmentManagerクラスのShowReplaceAppointmentAsyncメソッドを使う。予定を追加するときのShowAddAppointmentAsyncメソッドとの違いは、既存の予定を識別するための予定IDも引数として渡すことだ(次のコード)。実際のアプリでは、予定IDを保存し管理するロジックを作り込む必要がある。
private async void registerButton_Click(object sender, RoutedEventArgs e)
{
// 登録済みの予定IDを取得する
var appointmentId = ……省略……
// 新しい予定のオブジェクトを作る
var appointment = CreateAppointment();
// フライアウトを表示するターゲット(=ボタン)の位置とサイズ
var rect = GetElementRect(sender as FrameworkElement);
// 予定を更新するフライアウトを出す
var newAppointmentId
= await Windows.ApplicationModel.Appointments.AppointmentManager
.ShowReplaceAppointmentAsync(appointmentId, appointment, rect,
Windows.UI.Popups.Placement.Default);
}
Private Async Sub registerButton_Click(sender As Object, e As RoutedEventArgs)
' 登録済みの予定IDを取得する
Dim appointmentId = ……省略……
' 新しい予定のオブジェクトを作る
Dim appointment = CreateAppointment()
' フライアウトを表示するターゲット(=ボタン)の位置とサイズ
Dim rect = GetElementRect(sender)
' 予定を更新するフライアウトを出す
Dim newAppointmentId _
= Await Windows.ApplicationModel.Appointments.AppointmentManager _
.ShowReplaceAppointmentAsync(appointmentId, appointment, rect, _
Windows.UI.Popups.Placement.Default)
End Sub
ShowReplaceAppointmentAsyncメソッドも、予定を更新するフライアウトを出すだけであり、実際に更新されるかどうかはShowAddAppointmentAsyncメソッドと同様である。なお、本稿では紹介しなかったが、予定を削除するためのShowRemoveAppointmentAsyncメソッドもある。
AppointmentManagerクラスを使って、カレンダーアプリに予定を追加したり更新したりできる。また、カレンダーアプリに任意の日時を表示させることも可能だ。
予定コントラクトについては、次のドキュメントも参照してほしい。
Copyright© Digital Advantage Corp. All Rights Reserved.