変更通知機能

依存関係プロパティ、添付プロパティには、変更通知機能がある。
名前の通り、設定された値が変更すると通知する。要するに、
変わったら教えるよ
だ。この機能が、StyleやTemplateのTriggerにも活用されている。

<Border DockPanel.Dock="Top" Height="100">
<Border.Resources>
<Style TargetType="Border">
<Setter Property="Background" Value="AliceBlue"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Chocolate"/>
</Trigger>
</Style.Triggers>
</Style>
</Border.Resources>
</Border>

Borderコントロール内にマウスが入ると、背景色が変わる(抜粋)。
これは変更通知機能を使っているからこそできるもの。
Windows.Forms系ならマウスイベントをフックして~、背景色変えて~の実装が必要だったけど、
この程度なら、XAMLだけで済むというのが、XAMLファミリーのすごいところ、かなぁ。
なお、この変更通知、自分で検知して処理を加える事ができる。

/// <summary>
/// 依存関係プロパティをCLRプロパティの様に扱う為のプロパティ
/// </summary>
public bool IsJumping {
get {return (bool)GetValue(IsJumpingProperty);}
set {SetValue(IsJumpingProperty, value);}
}

/// <summary>依存関係プロパティ本体</summary>
public static readonly DependencyProperty IsJumpingProperty =
DependencyProperty.Register("IsJumping", typeof(bool),
typeof(MainWindow),
new UIPropertyMetadata(false, OnIsJumpingPropertyChanged));

/// <summary>
/// IsJumpingプロパティ変更通知イベントハンドラ
/// </summary>
/// <param name="dpObj">変更発生元</param>
/// <param name="e">イベント引数</param>
private static void OnIsJumpingPropertyChanged(
DependencyObject dpObj, DependencyPropertyChangedEventArgs e) {

if ((bool)e.OldValue) {
//...
}

if ((bool)e.NewValue) {
//...
}
}

UIPropertyMetadataの引数にメソッドを渡すことで変更通知を検知できる。
メソッドはstaticなので、インスタンスな変数等アクセスしようと思うなら
引数のDependencyObjectをキャストして使うしかない。
ここで良くあるのが、イベントへのハンドラ(メソッド)を登録する実装。

/// <summary>
/// IsJumpingプロパティ変更通知イベントハンドラ
/// </summary>
/// <param name="dpObj">変更発生元</param>
/// <param name="e">イベント引数</param>
private static void OnIsJumpingPropertyChanged(
DependencyObject dpObj, DependencyPropertyChangedEventArgs e) {

if ((bool)e.NewValue) {
var window = Window.GetWindow(dpObj);

if (window != null) {
window.PreviewMouseLeftButtonDown +=
new MouseButtonEventHandler(Window_PreviewMouseLeftButtonDown);
}
}
}

だけど、この登録したメソッドは、誰も削除してくれない。
不要になったら、自前で削除するしかない。
ほうっておくと、メモリリークの元になる。じゃあ、どうするの?ってのはまた別に書こう。
(追記)
注意点:以下の実装では動かない。

<Border DockPanel.Dock="Top" Height="100" Background="AliceBlue">
<Border.Resources>
<Style TargetType="Border">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Chocolate"/>
</Trigger>
</Style.Triggers>
</Style>
</Border.Resources>
</Border>

これは、「ローカル値」に背景色が設定されてしまっていて、Style Triggerが動かない為。

(2012/09/03追記)
続き的な話。↓
変更通知機能、その弐
スポンサーサイト
当サイトは基本をすっ飛ばしてます。基本文法等は、@ITをどうぞ
カテゴリー: WPF4 | コメント: 0 | トラックバック: 0


この記事へのコメント

コメントの投稿

非公開コメント


サイドバー背後固定表示サンプル

当ブログに書かれたソースコードは流用自由です。

バグ、スペルミス等はありうる事です。

ご利用の際は自己責任でお願いしますm(_ _)m