Windows Phone 7
初めての Windows Phone アプリケーション
初めて Windows Phone アプリケーションを作成するこつは、作成する価値があり、実際に取り組める程度の簡単なものをビルドすることです。そこで、NoteToMe という日常使用する簡単なユーティリティを作成してみます。このユーティリティの目的は、メッセージを入力してボタン 1 つで自分に送信できるようにすることです (図 1 参照)。
図 1 NoteToMe インターフェイス
今回の記事では多くのトピックを扱いますが、各トピックについては今後の記事でより詳しく説明する予定です。取り上げるトピックは、以下のとおりです。
- アプリケーションのレイアウトの作成
- 分離ストレージを使用したデータの保存と取得
- イベントとイベント処理
- タスクの作成と実行 (ランチャーおよびセレクター)
始めるにあたって、まず xbox.http://xbox.create.msdn.com からツールをダウンロードする必要があります。携帯電話のロックは解除したものの、まだ Windows Phone 7.5 ("Mango") にアップグレードしていなければ、今こそそのときです。Mango は、Windows Phone OS に数多くの新機能を提供します。
はじめに
多くの Windows Phone の開発者と同様、Windows Phone アプリケーションを作成するのに最良のツールは Visual Studio (コード作成に使用) と Expression Blend (それ以外に使用) の組み合わせだと考えるようになりました。そこで、まず Expression Blend を起動し、Windows Phone SDK 7.1 に基づき NoteToMe という名前の新しいアプリケーションを作成します。
最初にアプリケーション タイトルを変更しましょう。タイトルをクリックし、[プロパティ] ウィンドウで、タイトルを管理する [テキスト] プロパティを見つけます。Metro デザイン ガイドライン (Windows Phone 用のデザイン ガイドライン) は、タイトルをすべて大文字にすることを求めているため、タイトルを「NOTE TO ME」に変更します。
ページ タイトルを削除するには、タイトルをクリックして、[削除] をクリックします。
レイアウトを作成するため、ページ上部近くに小さな行が必要です。余白をクリックすると、行を配置する場所を視覚的に確認しながら選択できるガイド線が表示されます (図 2 参照)。
図 2 レイアウトの先頭行を配置する
もちろん、次のように、行のサイズは直接 XAML で入力して設定できます。
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
<RowDefinition Height="9*"/>
</Grid.RowDefinitions>
値の後ろのアスタリスクは相対サイズを示しており、この場合は 1 対 9 です。つまり、先頭行のサイズは 2 行目の 9 分の 1 です。
StackPanel にコントロールを 3 つ追加する
先頭行に次の 3 つのコントロールを並べて配置します。
- ラベルとして機能するテキスト ブロック
- 電子メール アドレスを保持するテキスト ブロック
- メッセージを送信するボタン
図 3 に、このデザインを示します。
図 3 先頭行の 3 つのコントロール
3 つのコントロールを行の 1 つの列に配置する場合は、なんらかの整理用コンテナーにまとめます。ここでは、水平方向に設定した StackPanel を使用します。StackPanel のパネルは、他のパネルの上か横に並べられます。
StackPanel を作成するには、ツール バーの [Layout] コントロールの横にある小さな白の矢印をクリックします (図 4 参照)。
図 4 StackPanel を追加する
コントロールを選択するため [StackPanel] をクリックします。次に、StackPanel を行にドラッグし、[レイアウト] ウィンドウで垂直方向と水平方向の配置を [拡大して表示] にし、余白をゼロに設定します (図 5 参照)。
図 5 StackPanel を配置する
TextBlock を追加し、フォント サイズを「32」、テキストを「To」に設定します。次に、TextBox を StackPanel の上にドラッグします (TextBlock はテキストの表示に使用し、TextBox はテキストの入力に使用するというわずかながら重大な違いがあります)。この TextBox に「Address」と名前を付けます。最後に、StackPanel にボタンを追加し、「Send」と名前を付け、Content に「Send」を設定します。
これを作成する XAML を図 6 に示します。
図 6 XAML を使って StackPanel をデザインする
<StackPanel
Margin="0"
Orientation="Horizontal">
<TextBlock
Margin="0,8"
TextWrapping="Wrap"
Text="To"
Width="42"
HorizontalAlignment="Left"
VerticalAlignment="Center"
FontSize="32" />
<TextBox
x:Name="Address"
Margin="0,0,0,-7"
TextWrapping="Wrap"
Text="foo@bar.com"
Width="293" />
<Button
x:Name="Send"
Content="Send"
Margin="0,4,0,0"
Width="124"
Click="Send_Click" />
</StackPanel>
Send ボタンに、Click="Send_Click" プロパティがあることに注意します。これはボタンをクリックして、[プロパティ] ウィンドウで [イベント] ボタンをクリックすることで作成します (図 7 参照)。
図 7 イベント ボタン
クリックすると、ボタンで実行できるすべてのイベントが表示されます。クリック イベントを見つけ、ダブルクリックします。ボタンのイベントが更新され、イベント ハンドラーのコード エディターが表示されます (Expression Blend の設定次第で、Expression Blend か Visual Studio のどちらかになります)。ここでは、イベント ハンドラーはそのままでかまいません。
private void Send_Click( object sender, RoutedEventArgs e )
{
}
メッセージ コントロールを追加する
ツール バーの [TextBox] コントロールをクリックし、TextBox を残りのページの半分を占めるようにドラッグします (残りの半分は、TextBox に何か入力するときに表示されるキーボードに使用します)。HorizontalAlignment を「拡大して表示」、VerticalAlignment を「上」、Margin をすべて「0」に設定します。次に、Width を「Auto」、Height を「244」に設定します。これらすべては TextBox をサイズ変更するときに目測で設定することもできますし、図 8 で示すように、TextBox をおおよその場所に描き [プロパティ] ウィンドウでプロパティを設定することもできます。
図 8 TextBox を追加する
コードを作成する
コントロールを配置したら、プログラムのロジックに着手できます。画面の左上隅に [プロジェクト] というタブがあります。すべての変更を保存してから、[プロジェクト] タブをクリックし、MainPage.xaml.cs を右クリックし、[Visual Studio で編集] をクリックします (図 9 参照)。
図 9 コード作成に着手する
仕様
ここでは、プログラムを使用するたびに To フィールドに入力する必要がなく、To フィールドには前回使用したときの入力内容が事前に設定される仕様にします (そう決めました)。
さらに、[Send] をクリックすると、事前に設定されたすべてのフィールドを使用して、電子メール プログラム向けに新しい電子メール メッセージを用意します。そのため、[Send] をクリックするだけ、またはメッセージを編集してから [Send] をクリックするだけでかまいません。
分離ストレージを使用する
アプリケーションから何回でも使えるように To フィールドの内容を保持するには、携帯電話のどこかにその内容を保存する必要があります。分離ストレージを使用すれば、アプリケーションの終了時にデータを保存できます。その名前が表しているように、分離ストレージを使用すれば、他のアプリケーションで保存したデータから分離および保護してデータを保存できます。分離ストレージは、非常に簡単に使用できます。
まず、次のように using ステートメントを追加します。
using System.IO.IsolatedStorage;
IsolatedStorageSettings 型のメンバー変数と、Isolated Storage ディクショナリのキーの役割を担う定数文字列を宣言し、電子メール アドレスを保存および取得できるようにします。
private IsolatedStorageSettings _isoSettings;
const string IsoKey = "EmailAddress";
Initialize the _isoSettings member in the constructor:
_isoSettings = IsolatedStorageSettings.ApplicationSettings;
電子メール アドレスを保存および取得する
分離ストレージには、文字列の保存と取得の 2 つの作業が必要です。文字列の保存は、ページから離れるときに行うのが最良です。Windows Phone ページを離れるときは、必ず OnNavigatedFrom メソッドが呼び出されます。このメソッドは自由にオーバーライドでき、分離ストレージにデータを保存するためにオーバーライドするのは理にかなっています。次のようになります。
protected override void OnNavigatedFrom(
System.Windows.Navigation.NavigationEventArgs e )
{
_isoSettings[IsoKey] = Address.Text;
base.OnNavigatedFrom( e );
}
これで、IsoKey キーの _isoSettings ディクショナリに電子メール アドレスが保存されるようになりました。ページに戻ったとき、この設定を復元できます。これは、コンストラクターから RestoreEmailAddress プライベート ヘルパー メソッドを呼び出して行います。
private void RestoreEmailAddress()
{
if (_isoSettings.Contains( IsoKey ))
Address.Text = _isoSettings[IsoKey].ToString();
}
復元を試みる前に、分離ストレージにキーがあるかどうかを確認していることに注意してください。これにより、初めてプログラムを実行したときに KeyNotFound 例外が発生するのを回避します。初めてプログラムを実行するときには、まだ何も分離ストレージに保存されていないことを思い出してください。
プログラムを初めて開始するときは、Address フィールドには何も表示されません。ユーザーが Address フィールドに電子メール アドレスを入力すると、そのアドレスが分離ストレージに保存され、次回プログラムを実行したときに復元されます。ユーザーがアドレスを変更した場合は、その新しいアドレスが復元されます。
タスク
Windows Phone 7.5 は、組み込みの携帯電話アプリケーション (メール、連絡先リスト、カメラなど) と対話するさまざまなタスクをサポートしています。タスクには、ランチャーとセレクターの 2 種類があります。セレクターは、情報を選択してプログラムに返すのに使用します (連絡先リストから電子メール アドレスを取得する場合など)。ランチャーは、データを返さないプログラムを起動するのに使用します。
ここでは、メッセージを送信するのに必要な情報をすべて用意するため、必要なフィールドに情報を指定して、電子メール ランチャーを呼び出します。電子メール ランチャーの Show を呼び出すと、指定したデータで電子メール アプリケーションが起動されますが、データは何も返されません (何も必要ないので問題ありません)。
電子メールを送信すると、他にもメッセージを送信する必要がある場合のために、プログラムに戻ります。
ランチャーを作成するためのすべての作業は、Send ボタンのクリック イベント ハンドラーにカプセル化します。EmailComposeTask (このランチャー) のインスタンスを作成することから始めましょう。これに必要なのは、次に示すように、フィールドに情報を設定して Show を呼び出すことだけです。
private void Send_Click( object sender, RoutedEventArgs e )
{
EmailComposeTask emailComposeTask = new EmailComposeTask();
emailComposeTask.Subject = "Send To Me";
emailComposeTask.To = Address.Text;
emailComposeTask.Body = Message.Text;
Message.Text = String.Empty;
emailComposeTask.Show();
}
Show を呼び出すと、メッセージの件名、アドレス、および本文が電子メール アプリケーションに渡されます。電子メール アプリケーションが複数ある場合は、どれを使用するかが質問されます。アドレスと書式が適切に設定された電子メール メッセージが作成され、送信の準備が整います。
アプリケーションのライフサイクル
メッセージの送信を完了するまで、ユーザーがアプリケーションの使用を一切中断することがないのなら、以下の作業は必要ありません。ただ、現実には、ユーザーはメッセージの作成を途中でやめ、他のアプリケーションを起動することがあります。戻ってきたときにそれまでの作業が失われていたら、ユーザーは不満でしょう。
これに対処する方法を理解するため、アプリケーションのライフサイクルについて少し学習する必要があります。また、Mango の最も強力な機能の 1 つである Fast Application Switching をサポートしたままでページの状態を保存する方法を簡単に説明します。
アプリケーションを (たとえば、スタート メニューから) 起動すると、Application Launching イベントが発生します。アプリケーションが開始されたときと、ユーザーがページに移動したときには、OnNavigatedTo メソッドが呼び出され、ページは実行状態になります。ユーザーが新しいアプリケーションを開始すると、それまでのアプリケーションは Application Deactivated イベントを受け取り、休止状態になります。携帯電話のメモリが少ない場合、アプリケーションは廃棄 (tombstone) 状態になる場合があります。
廃棄状態または休止状態から、アプリケーションは終了状態または再開状態に移行することがあります。ここで考える必要があるのは、アプリケーションが再開されるときのことです。
アプリケーションが休止状態の場合は、再開されたときに何も処理する必要がなく、むしろそのままにしておくことが望ましいでしょう。アプリケーションが休止状態になるときにページの状態が保存され、いつでも再開できます。
ただ、アプリケーションが廃棄状態の場合は、アプリケーションが再開されるときにページの状態を復元する必要があります。廃棄状態の間もアプリケーションが実行されていた (少なくとも休止状態だった) ようにユーザーには見えるためです。
そのため、次の 2 つのことを行う必要があります。
- ページの OnNavigatedFrom メソッドが呼び出されたときにページの状態を保存します。
- ページの OnNavigatedTo メソッドが呼び出されたとき、場合により状態を復元します。つまり、アプリケーションが廃棄状態の場合はページの状態を復元し、休止状態の場合は復元しません。
ページから離れるときに状態を保存する
ページが OnNavigatedFrom を受け取ったとき、どのような状態から再開されるかがわからないため、必要な場合に備えてページの状態を保存しておく必要があります。これは、Isolated Storage ディクショナリと非常によく似た構文の State ディクショナリを使用すれば、非常に簡単に行えます。ただ、State ディクショナリは、永久保存用には作成されておらず、実際にプログラムを終了したり、携帯電話の電源を切ったりすると破棄されることには注意が必要です。
まず、次に示すように、State ディクショナリのオフセットとして使用する StateKey 定数文字列を作成します。
const string StateKey = "MessageState";
OnNavigatedFrom メソッドで、State ディクショナリにページの状態を保存します (この場合は、MessageBox のコンテンツになります)。
protected override void OnNavigatedFrom(
System.Windows.Navigation.NavigationEventArgs e )
{
_isoSettings[IsoKey] = Address.Text;
State[StateKey] = Message.Text;
base.OnNavigatedFrom( e );
}
ページの作成時に状態を復元する
OnNavigatedTo メソッドが呼び出されたとき、アプリケーションが休止状態の場合には State を復元するための処理を何も行わず、廃棄状態の場合には処理を行う必要があります。
フラグに false を設定し、コンストラクターで true を設定することで休止状態か廃棄状態かを区別できます。アプリケーションが休止状態の場合はコンストラクターが呼び出されず、廃棄状態の場合はコンストラクターが呼び出されます (初めて構築されるためです)。次のようになります。
bool isNew = false;
public MainPage()
{
InitializeComponent();
isNew = true;
次のように、OnNavigatedTo のフラグを確認します。
protected override void OnNavigatedTo(
System.Windows.Navigation.NavigationEventArgs e )
{
if (isNew)
{
if (State.ContainsKey( StateKey ))
{
Message.Text = State[StateKey].ToString();
}
}
isNew = false;
base.OnNavigatedTo( e );
}
このテストにより、State ディクショナリから値を復元するのに不要な時間をかけずに済みます。これは、まずプログラムを通常どおりに実行し (このときに他のアプリケーションに切り替えるとプログラムは休止状態になります)、次にプログラムを強制的に廃棄状態にすることで確認できます。プログラムを強制的に廃棄状態にするには、プロジェクトを右クリックし、[プロパティ]、[デバッグ] タブを順にクリックし、[デバッグ中の非アクティブ化時に廃棄する] チェックボックスをオンにします。
チェックボックスをオンにした状態で実行すると、ページに戻ったときに時間がかかることに気付くでしょう。これは、ページの状態を復元する必要があるためです。
まとめ
今回の短い記事では、作りごたえのある Windows Phone アプリケーションを初めて作成する方法を紹介しました。まず、Expression Blend でアプリケーションを作成しました。そこでは、行を作成したうえで、StackPanel を使用してコントロールを配置しました。
次に Visual Studio に切り替え、ボタンのイベント ハンドラー用のロジックを作成し、電子メール アドレスを保存するのに分離ストレージを使用しました。State メモリを使用して、アプリケーションを廃棄状態から適切に再起動するようにしました。
最初に述べたように、それぞれのトピックに関してまだまだ説明が必要です。詳細については、今後の記事をお待ちください。
Jesse Liberty は、Windows Phone チームのシニア開発者コミュニティ エバンジェリストです。彼は有名な Yet Another Podcast (jesseliberty.com/podcast、英語) をホストしており、ブログ (jesseliberty.com/、英語) も充実しています。『Programming Reactive Extensions and LINQ』(Apress、2011 年) や『Migrating to Windows Phone』(Apress、2011 年) など、数多くのベストセラーの著者でもあります。ツイッターは twitter.com/JesseLiberty (英語) からフォローできます。
この記事のレビューに協力してくれた技術スタッフの Drew Batchelor および Cheryl Simmons に心より感謝いたします。