エクスポート (0) 印刷
すべて展開
情報
要求されたトピックは次のとおりです。しかし、このトピックはこのライブラリには含まれていません。

Windows Phone 8 のイベント

2014/06/18

対象: Windows Phone 8 および Windows Phone Silverlight 8.1 | Windows Phone OS 7.1

 

このトピックでは、イベントのプログラミングの概念について説明します。また、Windows Phone とそのプログラミング モデルにイベントの概念がどのように組み込まれているかについても説明します。Windows Phone のイベントの概念は、共通言語ランタイム (CLR) や .NET Framework で定義されているイベントの概念と本質的には同じです。WPF と同様に、イベントのハンドラーは、UI 要素の宣言の一部として XAML で割り当てることも、言語固有の構文を使用してコードで追加することもできます。Windows Phone は、ルーティング イベントの概念をサポートしています。この機能を使用すると、特定の入力イベントとデータ イベントを、その発生元オブジェクト以外のオブジェクトで処理できます。ルーティング イベントは、コントロール テンプレートの構成時や、アプリ ページのイベント ロジックを集中化する際に役立ちます。

このトピックは、次のセクションで構成されています。

 

イベントは、アクションの発生を知らせるために、オブジェクトによって送信されるメッセージです。アクションは、ユーザーが画面のタッチなどの対話的操作を行った場合や、クラスの内部ロジックによってトリガーされた場合などに発生します。イベントを発生させるオブジェクトをイベントの送信元と呼びます。イベントをキャプチャし、そのイベントに応答するオブジェクトをイベントの受信側と呼びます。イベントの基本的な目的は、時間固有の比較的軽量な情報を実行時にオブジェクトから送信し、必要に応じてアプリ内の他のオブジェクトに渡すことです。

Windows Phone のイベント

一般に、Windows Phone イベントは CLR イベントなので、マネージ コードで操作できます。基本的な CLR イベントの操作方法を把握していれば、いくつかの関連の概念をスムーズに理解できます。ただし、ハンドラーのアタッチのような基本的なタスクを行うために、CLR のイベント モデルについて詳しく学ぶ必要はありません。

Windows Phone ベースの一般的なアプリの UI はマークアップ (XAML) で定義されるため、UI イベントをマークアップ要素からランタイム コード エンティティに関連付けるときの原則の一部は、他の Web テクノロジ (ASP.NET など) や、HTML DOM を操作する場合の原則と似ています。Windows Phone では、XAML で定義された UI のランタイム ロジックを提供するコードは、分離コードまたは分離コード ファイルと呼ばれることがあります。Visual Studio のソリューション ビューでは、この関係がグラフィカルに表示されるだけでなく、依存する入れ子の分離コード ファイルと参照先の XAML ページも表示されます。

Windows Phone には、独自のランタイム オブジェクト モデル内で機能する CLR イベントのほかにも、スクリプト ベースのハンドラーを HTML レベルで呼び出すことのできるイベント (OnError など) もいくつかあります。これらのイベントは公開され、HTML DOM 内のプラグイン インスタンスに対して実行されるスクリプトで処理できます。アプリの一般的なイベント モデルとして、この処理は最初に HTML スクリプトが行うことになるので、イベントを HTML で処理する場合は、そのイベントをマネージ API に渡さないようにしてください。

Windows Phone は UI テクノロジなので、最も一般的なタスクの 1 つは、ユーザー入力を UI に取り込むことです。たとえば、UI には、ユーザーが情報を送信したり、アプリの状態を変更したりするためにタップする必要のあるボタンが組み込まれることがあります。

Windows Phone ベースのアプリの UI を定義するには、通常は XAML を生成します。この XAML は、Blend for Visual Studio などのデザイナーや、Windows Phone などの大規模な IDE のデザイン サーフェイスから出力できます。また、プレーンテキスト エディターやサードパーティ製の XAML エディターで記述することもできます。この XAML の生成タスクの一環として、個々の UI 要素を指定するすべての属性を定義する際に、その UI 要素にイベント ハンドラーを関連付けることができます。

Windows Phone を使用している場合は、そのデザイン機能を利用すると、簡単に XAML のイベント ハンドラーを関連付け、分離コードで定義することができます。その際、ハンドラーの自動名前付けスキーマを指定する必要があります。

Windows Phone 用の .NET Framework クラス ライブラリのドキュメントを利用して特定のイベントを調べ、そのデリゲートを特定することもできます。記述するハンドラーは、そのデリゲート シグネチャに対応している必要があります。前に示した例では、最適なデリゲートは RoutedEventHandler です。

メモメモ:

Windows Phone のイベント ハンドラー関数は、(空のパラメーター値であっても) パラメーター値を指定して呼び出すことはできません。これは、HTML DOM のイベント ハンドラー構文との大きな違いです。XAML の属性値はハンドラー名だけを参照します。情報を渡す役割を担うのは他のメカニズム (ハンドラーに渡される入力パラメーターなど) です。

オブジェクトが UI であり、XAML で宣言される場合、イベント ハンドラー コードは、XAML ページの分離コードとなる部分クラスに定義する必要があります。

部分クラス内のイベント ハンドラーは、対応するイベントが使用する CLR デリゲートに基づき、メソッドとして記述します。イベント ハンドラー メソッドのアクセス レベルは、public と private のどちらでもかまいません。アクセス レベルを private に設定できるのは、XAML によって作成されるハンドラーおよびインスタンスが最終的にコード生成によって結合されるためです。通常は、クラス内でイベント ハンドラー メソッドを public にすることはお勧めできません。

マネージ Windows Phone イベント用に記述したハンドラーは、そのハンドラーが呼び出された際に、その都度入力として使用できる 2 つの値にアクセスできます。その最初の値が sender です。これは、ハンドラーがアタッチされているオブジェクトへの参照です。sender パラメーターは、Object 基本型として型指定されます。Windows Phone のイベント処理では、sender をより正確な型にキャストするという手法が共通しています。この手法は、sender オブジェクト自体で状態を確認または変更する必要がある場合に便利です。それぞれのアプリ設計に基づき、sender のキャスト先として安全な型をハンドラーのアタッチ先やその他の設計の情報を基に把握する必要があります。

2 つ目の値はイベント データです。これは通常、e パラメーターとしてシグネチャに表示されます。どのイベントも、CLR のイベント モデルに従って特定の種類のイベント データを送信します。そのデータは、EventArgs を継承するクラス (または EventArgs 自体) のインスタンスとしてキャプチャされます。使用できるイベント データのプロパティを見つけるには、処理対象のイベントに割り当てられているデリゲートの e パラメーターを参照した後、Visual Studio の IntelliSense か、Windows Phone 用の .NET Framework クラス ライブラリを使用します。一部の Windows Phone イベントでは、EventHandler<TEventArgs> デリゲートまたはその他のジェネリック ハンドラー型を使用します。多くの場合、イベント定義は、特定の EventArgs 派生イベント データ クラスを使用してジェネリックを制約します。次に、ハンドラー メソッドが、その EventArgs 派生イベント データ クラスを 2 番目のパラメーターとして直接取るよう記述する必要があります。

イベントによっては、イベントの発生を検知することと同様に EventArgs 派生クラスのイベント データが重要となります。これが特に当てはまるのが入力イベントです。キーボード イベントの場合、キーボード上のキーが押されると、同じ KeyUp イベントおよび KeyDown イベントが発生します。どのキーが押されたかを判定するには、イベント ハンドラーで使用できる KeyEventArgs にアクセスする必要があります。

イベント ハンドラーをオブジェクトに割り当てる手段は、XAML 以外にもあります。イベント ハンドラーをマネージ コードで特定のオブジェクト (XAML では使用できないオブジェクトも含む) に追加するには、CLR 言語固有のイベント ハンドラー追加構文を使用します。

C# の構文では、+= 演算子を使用します。イベント ハンドラー メソッド名を使用する新しいデリゲートを宣言することによって、ハンドラーをインスタンス化します。

ランタイム UI に表示されるオブジェクトにイベント ハンドラーをコードで追加する場合、Windows Phone では、LoadedOnApplyTemplate など、オブジェクトの有効期間イベントまたはコールバックに応じてハンドラーを追加するのが一般的です。これにより、該当するオブジェクトのイベント ハンドラーは、実行時にユーザーが発生させるイベントに対応できるようになります。

もう 1 つは、イベント ハンドラーに Handles キーワードを指定するという方法です。この方法は、読み込みの時点からオブジェクトの有効期間を通じてオブジェクト上にハンドラーが存在している必要がある場合に適しています。XAML に定義されたオブジェクトで Handles を使用するには、Name または x:Name を指定する必要があります。この名前は、Handles 構文の Instance.Event の部分に必要なインスタンス修飾子となります。この場合は、他のイベント ハンドラーのアタッチを開始する、オブジェクトの有効期間に基づくイベント ハンドラーは不要です。Handles の関連付けは、XAML ページのコンパイル時に作成されます。

Sub textBlock1_MouseEnter(ByVal sender As Object, ByVal e As MouseEventArgs) Handles textBlock1.MouseEnter
'....
End Sub
Sub textBlock1_MouseLeave(ByVal sender As Object, ByVal e As MouseEventArgs) Handles textBlock1.MouseLeave
'....
End Sub
メモメモ:

Visual Studio とその XAML デザイン サーフェイスでは、一般に、Handles キーワードの代わりにインスタンス処理の手法が推奨されます。その理由は、XAML でのイベント ハンドラーの設定は Windows Phone のデザイナーと開発者が通常行うワークフローに含まれますが、Handles キーワードを使用する手法は XAML でのイベント ハンドラーの記述とは性質が異なるためです。

Windows Phone がサポートするルーティング イベントの概念は、いくつかの入力イベントに対応しています。これらの入力イベントは、基本クラスで定義され、ユーザーとのやり取りや入力をサポートするほとんどの UI 要素に存在します。次に、ルーティング イベントである入力イベントの一覧を示します。

ルーティング イベントとは、オブジェクト ツリーの子オブジェクトから渡され (ルーティングされ)、一連の親オブジェクトまでルーティングされる可能性のあるイベントのことです。この場合のオブジェクト ツリーは UI の XAML 構造に似ており、このツリーのルートは XAML におけるルート要素に相当します。実際のオブジェクト ツリーは、プロパティ要素タグなどの XAML 言語機能が含まれていないので、XAML とはやや異なります。ルーティング イベントは、基本的に、イベントを発生させる XAML オブジェクト要素の子からそれらが含まれる親オブジェクト要素へと上方に "バブル" ルーティングされるものと考えることができます。イベントの発生とそのイベント データはイベント ルート上のオブジェクトに報告され、最終的にルート要素に到達します(これまでに DHTML などの特定の Web テクノロジを使用したことがあれば、"バブル" の概念を知っているかもしれません)。

メモメモ:

XAML は、バブル ルーティングに似た "トンネル" ルーティングをサポートしています。この方式では、ルーティング イベントは最初にページ/オブジェクト ツリーのルート要素によって処理され、オブジェクト ツリー内を下ってそのイベント ソースまで送られます。Windows Phone では、"トンネル" ルーティング イベントは使用されません。Windows Phone におけるイベントは、"バブル" ルーティング方式に従うか (この場合、イベントはルーティング イベントと呼ばれます)、まったくルーティングされません。wphone と XAML のルーティング イベントの動作には、この他にも API レベルの相違があります。

RoutedEventArgs の OriginalSource プロパティ

イベントがバブル ルーティングによって移動すると、sender はイベントが発生したオブジェクトと同じものではなくなります。sender は、呼び出されたハンドラーがアタッチされているオブジェクトです。多くの場合、注目されるのは sender ではなく、キーボードのキーが押されたときにどのオブジェクトにフォーカスがあったかなどの情報を調べることです。そのためには、OriginalSource プロパティの値に注目します。

OriginalSource は、ルートのすべての位置で、ハンドラーがアタッチされているオブジェクトではなく、イベントを発生させた元のオブジェクトを報告します。これが役に立つ状況の例として、キーボード フォーカスを持つコントロールや、イベントを発生させたコントロールに関係なく、特定のキーの組み合わせを "ショートカット キー" つまりアクセラレータとする必要のあるアプリについて考えてみます。オブジェクト ツリーでは、フォーカスのあるオブジェクトは、リスト ボックスの項目リストとして深いレベルまで入れ子になっていることもあれば、UI 全体を構成する多数のオブジェクトの 1 つである場合もあります。アクセラレータを検出するために、フォーカスを取得できる個々のアプリ オブジェクトにハンドラーをアタッチすることは、明らかに実際的ではありません。しかし、キーボード イベントはバブル ルーティングされるので、最終的にイベント ルート内のルート オブジェクトに到達します。したがって、KeyDown イベントは最終的にはルート オブジェクトまで移動するという動作を利用することにより、1 つの KeyDown ハンドラーをルート オブジェクトにアタッチできます。このハンドラーは、押されたキーが目的のアクセラレータ アクションにとって有効なキーの組み合わせであるかどうか、またはアクションが不要であるかどうかを判断します。

ヒントヒント:

テンプレート コントロールを作成する場合は、入力のバブルを使用すると特に便利です。テンプレートを持つすべてのコントロールで、新しいテンプレートをコンシューマーによって適用できるため、既定のテンプレート XAML で宣言されているイベント処理がすべて削除される可能性があります。クラス定義で OnApplyTemplate のオーバーライドの一部としてハンドラーをアタッチすることにより、コントロール レベルのイベント処理を提供し、コントロールのルートまで上方に伝達される入力イベントをキャッチすることができます。

Handled プロパティ

特定のルーティング イベントのイベント データ クラスには、Handled というプロパティが含まれているものがあります。「MouseButtonEventArgs.Handled」、「KeyEventArgs.Handled」、「DragEventArgs.Handled」、および「ValidationErrorEventArgs.Handled」の例を参照してください。Handled は設定可能なブール値プロパティです。

Handled プロパティを true に設定した場合、Windows Phone のイベント システムに影響します。イベント データでこの値を true に設定した場合、ほとんどのイベント ハンドラーでイベントのルーティングがそこで停止されます。イベントは、ルート上にあるアタッチされている他のハンドラーには伝達されません。イベントのコンテキストでアクションとしての "handled" が意味するものと、アプリの応答方法は、アプリの設計しだいです。ただし、イベント ハンドラーで Handled を設定した場合は、Windows Phone イベント システムの動作に注意する必要があります。

すべてのルーティング イベントをこれと同じ方法で取り消せるわけではありません。GotFocusLostFocus、および MouseMove は常にルートまで伝達され、対応するイベント データ クラスには、その動作に作用する Handled プロパティが存在しません。これらのイベントについては、OriginalSource の値を調べながら、不要なイベント処理を回避し、イベントの本来の意味や UI レイアウトでの入力イベントの発生元を正しく理解するようにしてください。

メモメモ:

ルーティング イベント用の Handled プロパティの概念は、XAML にもあります。XAML では、すべてのルーティング イベント データ クラスに Handled プロパティが存在します。一方、Windows Phone では、関連のイベントのルーティングを取り消すために使用できるのは、独自の Handled プロパティを持つ特定のイベント データ クラスに限られます。

ビジュアル ツリー外のルーティング イベント

Windows Phone の一部のオブジェクトは、プライマリ ビジュアル ツリー (概念的にはメイン ビジュアル上のオーバーレイのようなもの) と関係しています。このようなオブジェクトは、すべてのツリー要素とビジュアル ルートを関連付ける通常の親子関係には含まれません。たとえば、表示される Popup などがこれに該当します。Popup からのルーティング イベントを処理する場合、Popup 要素そのものではなく、Popup 内の特定の UI 要素にハンドラーを配置する必要があります。Popup のコンテンツに対して実行される複合化の内部のルーティングに依存しないでください。ルーティング イベントのイベント ルーティングは、メイン ビジュアル ツリーに沿った形でしか機能しないためです。Popup は、従属する UI 要素の親とは見なされず、(たとえば、Popup の既定の背景を入力イベントのキャプチャ領域として使用しようとしても) ルーティング イベントを受け取ることはできません。

特定の既存 Windows Phone コントロールでは、入力イベントに、この Handled の概念が内部的に使用されていることがあります。この場合、ユーザー コードからは、入力イベントが発生しないように見えることがあります。たとえば、Button クラスには、一般的な入力イベント MouseLeftButtonDown を意図的に処理するロジックが含まれています。一般に、.NET Framework ライブラリの特定のコントロール クラスのリファレンス トピックには、そのクラスが実装しているイベント処理の動作について説明があります。場合によっては、サブクラスで OnEvent メソッドをオーバーライドして、その動作を変更したり、処理を追加したりすることもできます。たとえば、TextBox.OnKeyDown をオーバーライドすると、TextBox 派生クラスのキー入力に対する動作を変更できます。

処理済みのルーティング イベントのハンドラーの登録

既に説明したように、Handledtrue に設定すると、ほとんどのハンドラーが動作しなくなります。API の AddHandler を活用すると、ルート内の他のハンドラーが Handledtrue に設定していても、ルートに対して必ず呼び出されるハンドラーをアタッチできます。使用しているコントロールが内部の複合ロジックまたはコントロール固有のロジックでイベントを既に処理しているが、コントロール インスタンスやルート内の上位の要素でそのイベントに応答する必要がある場合に、この手法が役立ちます。ただし、この手法は、Handled の用途と矛盾し、コントロールの本来の用途やオブジェクト モデルに違反する可能性があるため、使用する際は注意が必要です。

詳細と使用例については、「AddHandler」を参照してください。

Windows Phone では、ユーザーが発生させたイベントを処理するハンドラーのコンテキストで実行できる操作は限られています。そのような操作の一覧を次に示します。

Windows Phone でユーザーが発生させるイベントには、マウス イベント (MouseLeftButtonDown など) とキーボード イベント (KeyDown など) があります。このようなイベントに基づくコントロールのイベントも、ユーザーが発生させるイベントと見なされます。

ユーザーによる操作が必要な API 呼び出しは、イベント ハンドラーでできるだけ早く行う必要があります。その理由は、Windows Phone のユーザー操作の原則では、イベント発生後の一定時間内に呼び出しを行うことも必要とされるためです。Windows Phone では、この時間は約 1 秒です。

アプリの有効期間中にイベント ハンドラーを削除することが必要になる場合もあります。イベント ハンドラーを削除するには、CLR 言語固有の構文を使用します。C# では、-= 演算子を使用します。Visual Basic では、RemoveHandler 関数を使用します。どちらの場合も、イベント ハンドラー メソッド名を参照します。

textBlocks_MouseEnter という名前のイベント ハンドラーをターゲット オブジェクトの textBlock1 から削除する方法を次のコードに示します。

void Cleanup()
{
    textBlock1.MouseEnter -= textBlocks_MouseEnter;
}

XAML 属性を使用してイベントを追加した場合でもハンドラーを削除できます。ハンドラーがアタッチされている要素の Name 値を指定した場合は、後でコードのオブジェクト参照が提供されるため、こちらの方が容易です。ただし、必要に応じてオブジェクト ツリー内から必要なオブジェクト参照を探すこともできます。

Windows Phone では、コマンド実行がサポートされる UI 要素は少数です。コマンド実行では、基になる実装で入力関連のルーティング イベントを使用し、1 つのコマンド ハンドラーを呼び出して関連する UI 入力 (特定のマウス操作、特定のショートカット キー) の処理を有効にします。UI 要素でコマンド実行を使用できる場合は、独立した入力イベントの代わりにコマンド実行 API を使用することを検討してください。詳細については、次のいずれかを参照してください。

ButtonBase.Command

Hyperlink.Command

関連項目

その他の技術情報

表示:
© 2014 Microsoft