Silverlight のカスタム クラスのイベントの定義

ビューの切り替え:
スクリプトなし
Silverlight
Silverlight のカスタム クラスのイベントの定義
この記事は翻訳者によって翻訳されたものです。 このページおよび元の英語コンテンツを同時に表示させるには、[ライトウェイト] に切り替えます。

定義した Silverlight のクラスでは、CLR イベント システムの規則に従って独自のイベントも定義できます。 一般的ではありませんが、構造体やインターフェイスのイベントを定義することもできます。 カスタム イベントを定義するには、次の一連のタスクを実行します。

  • カスタム型のイベント メンバーを定義します。

  • カスタム イベントのハンドラーを表すデリゲート クラスを定義するか、既存のデリゲートを再利用します (適切なデリゲートが見つかった場合)。

  • 特殊なデリゲートを定義する場合。 委任で使用されるイベント データ クラスを定義します。

  • 独自のクラス ロジックからイベントを発生させます。

  • 省略可能: プロテクト仮想メソッドを公開し、派生クラスによるイベントの生成を可能にするか、派生クラスが基本クラスによるイベントの使用方法に作用できるようにします。

必須コンポーネント

このトピックは、Silverlight のイベントについて、イベント コンシューマーの観点から理解していることを前提としています。「Silverlight のイベントの概要」を参照してください。

また、デリゲートの概念などの CLR イベント システムの規則を理解していることも前提としています。「イベント、デリゲート、および CLR イベント システムの規則」を参照してください。

イベントの定義

  • event キーワードを使用して、クラスにイベント メンバーを定義します。 通常、イベントは public として定義します。そうすると、ユーザーが作成したクラスのインスタンスでそのイベントを処理できます。

イベント定義の一部で、イベントのハンドラーとして機能するデリゲートを指定します。 次のセクションで説明するように、新しいデリゲート クラスを定義するのが一般的ですが、 コードで使用するライブラリに適切なデリゲートが存在する場合は、それを再利用してもかまいません。

たとえば、次のコードでは、CircularFile というカスタム コントロール クラスの CapacityExceeded イベントを定義しています。

C#
public class CircularFile : ContentControl {
...
    public event CapacityExceededHandler CapacityExceeded;
}
Visual Basic
Public Class CircularFile
Inherits ContentControl
...
    Public Event CapacityExceededHandler CapacityExceeded
End Class

この例では、イベントの発生時に独自のイベント データを渡すという目的があるため、カスタム イベント データ クラスを組み込んだ特殊なデリゲート型を定義する必要があります。

メモ メモ :

このほかに、イベントに対して EventHandler<TEventArgs> 汎用デリゲートを使用する方法もあります。 その場合、汎用の形式に特殊なイベント データの型で制約を加えます。 たとえば、public event EventHandler<CapacityExceededEventArgs> CapacityExceeded; のように指定します。

デリゲートの定義

デリゲートを定義するには、コードの型レベルで新しい型を定義します。ただし、構文は実際にはメソッド定義に似たものになります。 このとき重要なのが delegate キーワードです。

イベント ハンドラーのデリゲートは通常は public にし、その戻り値の型は void である必要があります (Visual Basic の場合は、本体なしで Sub として定義する必要があります)。

イベント ハンドラーのデリゲートには、常に 2 つのパラメーターが必要です。 最初のパラメーターは、Object 型にする必要があります。このパラメーターの名前は、デリゲート定義とデリゲートに基づく通常のハンドラーのどちらでも、慣例では sender です。 2 つ目のパラメーターは、直接、間接を問わず、EventArgs に基づくカスタム クラスにする必要があります。慣例では、このパラメーターの名前は e です。

たとえば、次のコードでは、前の例で参照されている CapacityExceededHandler デリゲートを定義しています。

C#
public delegate void CapacityExceededHandler (object sender, CapacityExceededEventArgs e);
Visual Basic
Public Delegate Sub CapacityExceededHandler (sender As Object, e As CapacityExceededEventArgs)
イベント データ クラスの定義

イベントがそのイベントに固有のプロパティを 1 つ以上報告する際に、イベント データ クラスを定義します。 たとえば、サンプルの CapacityExceeded イベントは、超過している容量をパーセントと絶対数で報告します。この容量は、2 種類のプロパティで報告されます。

呼び出し元からイベントを発生させる場合は、通常、イベント データのコンストラクターを定義して、呼び出し元がイベントを発生させる際に特定のイベント データを渡せるようにする必要があります。 または、関連のプロパティを設定可能にし、少なくとも既定のコンストラクターを指定する必要があります。 イベント データ クラスを宣言する例を次に示します。

C#
public class CapacityExceededEventArgs : EventArgs
{
   private Int32 exceededTotal;
   private Double exceededPercentage;

   public CapacityExceededEventArgs(Int32 exceededTotal, Double exceededPercentage)
   {
      this.exceededTotal = exceededTotal;
      this.exceededPercentage = exceededPercentage;
      // not shown - validation for input
   }

   public Int32 ExceededTotal {
      get { return this.exceededTotal; }
   }
   public Double ExceededPercentage {
      get { return this.exceededPercentage; }
   }
}
ヒント ヒント :

イベント データ クラスには、状況に応じてメソッドを追加することもできます。たとえば、MouseEventArgs クラスは単に Position プロパティを持つだけでなく、GetPosition メソッドを定義します。これにより、パラメーターを GetPosition に渡し、指定したオブジェクトの座標空間に対する相対位置を取得できます。

クラスからイベントを発生させる

このタスクは、イベントの性質とクラスの用途に大きく左右されます。 最も一般的なのは、イベントを使用して、クラスのインスタンスの状態の変化を報告するというシナリオです。 前の CapacityExceeded の例の場合、論理的には、クラスで関連のプロパティの値に対してランタイム チェックを実行し、そのプロパティに何か重要な変化が起こっていればイベントを発生させるというシナリオになります。 イベントを発生させるには、まずイベント データのインスタンスを作成する必要があります。

C#
...
Int32 overflow = this.CurrentContent - this.Capacity;
CapacityExceededEventArgs newData = new CapacityExceededEventArgs(overflow, (Double) this.CurrentContent / this.Capacity);

イベント データを作成した後は、イベントを呼び出す構文を使用すると、最も簡単にイベントを発生させることができます。

C#
CapacityExceeded(this, newData);

ただし、サブクラス化が可能な状態のクラスで使用されることのあるイベント パターンもあります。これを代わりに使用することを検討してください。 このパターンについては、次のセクションで説明します。

OnEvent パターンの実装

On Event パターンは、.NET Framework の初期バージョン以降、CLR イベントのベスト プラクティスとして文書化されています。 OnEvent パターンの目的は、クラスからサブクラス化されたクラスで、定義済みのイベントを抑制できるようにすることです。これは、サブクラスの方でより特殊なイベントを発生させる場合に便利です。 OnEvent パターンを実装するには、イベントの呼び出しだけを行うプロテクト仮想メソッドをクラスで公開する必要があります。 派生クラスもイベントを生成する際にイベント データの独自の解釈を提供しようとすることがあるため、入力パラメーターとして渡されるイベント データに基づいてイベントを発生させるようにしてください。 このパターンを機能させるには、必要に応じてオーバーライドが呼び出されるように、イベント生成時に独自のクラスで仮想メソッドを呼び出す必要があります。

C#
protected virtual void OnCapacityExceeded(CapacityExceededEventArgs e)
{
    if (CapacityExceeded != null) {CapacityExceeded(this, e);}
}
// to raise the event, do this:
...
OnCapacityExceeded(newData);
カスタム ルーティング イベント

Silverlight は、カスタム ルーティング イベントの作成をサポートしていません。 Silverlight で使用できるルーティング イベントは、既存の Silverlight クラスで定義されているものに限られます。その一覧については、「Silverlight のイベントの概要」の「ルーティング イベント」を参照してください。

参照

概念