プロパティ変更イベント

更新 : 2007 年 11 月

Windows Presentation Foundation (WPF) では、プロパティ値の変更に応答して発生するさまざまなイベントが定義されています。通常、プロパティは依存関係プロパティです。イベント自体は、ルーティング イベントのこともあれば、標準の 共通言語ランタイム (CLR) イベントのこともあります。要素ツリーを通じて適切にルーティングされるプロパティ変更もあれば、プロパティが変更されたオブジェクトにのみ関係するプロパティ変更もあるため、イベントの定義は状況によって異なります。

プロパティ変更イベントの識別

シグニチャ パターンまたは名前付けパターンに基づいてプロパティ変更を報告するすべてのイベントが、プロパティ変更イベントとして明示的に識別されるわけではありません。通常、ソフトウェア開発キット (SDK) ドキュメント内のイベントの説明では、イベントがプロパティ値の変更に直接結び付くものであるかどうかが示されており、プロパティとイベントのクロス リファレンスが提供されます。

RoutedPropertyChanged イベント

特定のイベントでは、プロパティ変更イベントで明示的に使用されるイベント データ型とデリゲートを使用します。イベント データ型は RoutedPropertyChangedEventArgs<T> であり、デリゲートは RoutedPropertyChangedEventHandler<T> です。イベント データもデリゲートも、ジェネリック型パラメータを使用します。これは、ハンドラを定義するときに、変更するプロパティの実際の型を指定するために使用されるものです。イベント データは OldValue および NewValue という 2 つのプロパティを持ち、これらはイベント データ内で型引数として渡されます。

名前の "Routed" 部分は、プロパティ変更イベントがルーティング イベントして登録されることを示しています。プロパティ変更イベントのルーティングには、子要素 (コントロールの複合部分) のプロパティが値を変更した場合に、コントロールのトップレベルがプロパティ変更イベントを受信できるというメリットがあります。たとえば、Slider など、RangeBase コントロールが組み込まれたコントロールを作成するとします。スライダ部分で Value プロパティの値が変わった場合、その部分ではなく親コントロールでその変更を処理する必要がある場合があります。

古い値と新しい値があるため、このイベント ハンドラがプロパティ値の検証コントロールとして使用される可能性があります。しかし、プロパティ変更イベントの多くは、このような目的で設計されているわけではありません。通常、値の提供は、他のロジックのコードでその値を処理するために行われます。しかし、イベント ハンドラ内から値を実際に変更することはお勧めできません。また、ハンドラの実装方法によっては、意図しない再帰が生じることもあります。

プロパティがカスタム依存関係プロパティの場合、または、インスタンス化コードを定義した派生クラスで操作している場合、WPF プロパティ システムには、プロパティ変更を追跡する優れたメカニズムが組み込まれています。それは、CoerceValueCallback および PropertyChangedCallback というプロパティ システム コールバックです。WPF プロパティ システムを使用して検証および強制型変換を行う方法の詳細については、「依存関係プロパティのコールバックと検証」および「カスタム依存関係プロパティ」を参照してください。

DependencyPropertyChanged イベント

プロパティ変更イベントのシナリオには、DependencyPropertyChangedEventArgsDependencyPropertyChangedEventHandler のペアも含まれます。これらのプロパティ変更のイベントはルーティングされません。これらは、標準の CLR イベントです。DependencyPropertyChangedEventArgs は、EventArgs から派生したものではなく、特殊なイベント データ レポート型です。DependencyPropertyChangedEventArgs は構造体であり、クラスではありません。

DependencyPropertyChangedEventArgsDependencyPropertyChangedEventHandler を使用するイベントは、RoutedPropertyChanged イベントより多少一般的です。IsMouseCapturedChanged は、これらの種類を使用するイベントの例です。

RoutedPropertyChangedEventArgs<T> と同様、DependencyPropertyChangedEventArgs も、プロパティの古い値と新しい値を報告します。そのため、値を使用して行う操作に関して同じ注意が当てはまります。イベントに応答して送信元で値を変更することは、一般的にはお勧めできません。

プロパティ トリガ

プロパティ変更イベントに密接に関係する概念がプロパティ トリガです。プロパティ トリガはスタイルまたはテンプレート内に作成され、プロパティ トリガが割り当てられるプロパティの値に基づく条件付きの動作を作成できます。

プロパティ トリガのプロパティは、依存関係プロパティです。これは (多くの場合) 読み取り専用の依存関係プロパティです。コントロールによって公開される依存関係プロパティが、プロパティ トリガになるように少なくとも部分的に設計されている場合の良い指標が、プロパティ名の先頭が "Is" がどうかということです。この名前付けがされたプロパティは、多くの場合、読み取り専用のブール型の依存関係プロパティです。このプロパティの主要なシナリオは、リアルタイム UI に影響を及ぼす可能性があるためにプロパティ トリガの候補である、レポート コントロール ステートです。

これらのプロパティの一部は、専用のプロパティ変更イベントも持ちます。たとえば、プロパティ IsMouseCaptured は、プロパティ変更イベント IsMouseCapturedChanged を持ちます。プロパティ自体は読み取り専用であり、その値は入力システムによって調整され、入力システムがリアルタイムの変更のたびに IsMouseCapturedChanged を発生します。

プロパティ トリガを使用してプロパティの変更に対処する場合は、本当のプロパティ変更イベントに比べ、いくつかの制限があります。

プロパティ トリガは、完全一致ロジックを通じて動作します。プロパティと、トリガが処理する特定の値を示す値を指定します。次に例を示します。<Setter Property="IsMouseCaptured" Value="true"> ... </Setter>。この制限のため、ほとんどのプロパティ トリガの使用は、ブール型のプロパティか、有効な値の範囲が管理可能で、各ケースに対してトリガを定義できる専用の列挙値を使用するプロパティが対象です。または、プロパティ トリガは、項目のカウントがゼロに達した場合など、特別な値に対してのみ存在する可能性があります。プロパティ値がゼロから再び変更するケースに対処するトリガはありません (すべてのケースに対応するトリガではなく、コード イベント ハンドラ、または、値がゼロ以外のときにトリガ状態を再び元に戻す既定の動作が必要です)。

プロパティ トリガの構文は、プログラミングの "if" ステートメントに似ています。トリガ条件が true の場合、プロパティ トリガの "本体" が "実行" されます。プロパティ トリガの "本体" はコードではなく、マークアップです。そのマークアップは、1 つ以上の Setter 要素を使用して、スタイルやテンプレートが適用されているオブジェクトの他のプロパティを設定するように制限されています。

さまざまな有効値から成るプロパティ トリガの "if" 条件をオフセットするには、一般には、Setter を使用して同じプロパティ値を既定値に設定することをお勧めします。こうすることで、トリガ条件が true の場合は、Trigger が含む setter が優先され、トリガ条件が false の場合は、Trigger 内にない Setter が優先されます。

プロパティ トリガは、通常、1 つ以上の外観プロパティが、同じ要素の別のプロパティの状態に基づいて変更されるシナリオに適しています。

プロパティ トリガの詳細については、「スタイルとテンプレート」を参照してください。

参照

概念

ルーティング イベントの概要

依存関係プロパティの概要