しっぽを追いかけて

ぐるぐるしながら考えています

Unity と猫の話題が中心   掲載内容は個人の私見であり、所属組織の見解ではありません

Dependency Property の変更をイベントで通知する

Visibility の変更時に特定の処理をさせようと思ったらストアアプリでは VisibilityChanged のイベントは Window など限られたコントロールにしか用意されていませんでした

WPF の場合 DependencyPropertyDescriptor というクラスを利用すれば行えますが、ストアアプリにはない!

ないならば作るしか・・・と思ったら MSDN Blog で実装コードが紹介されていました!

Getting change notifications from any dependency property in Windows Store Apps - Cloudy Computing - Site Home - MSDN Blogs

この記事のコードを参考に書いてみたのが次のコード

/// <summary>
/// 依存関係プロパティの変更を監視するクラス
/// </summary>
/// <typeparam name="T">監視対象の依存関係プロパティ値の型</typeparam>
public class DependencyPropertyWatcher<T> : DependencyObject, IDisposable
{
    #region Value 依存関係プロパティ
    /// <summary>
    /// 監視対象値 依存関係プロパティ
    /// </summary>
    public static readonly DependencyProperty ValueProperty
        = DependencyProperty.Register(
        "Value",
        typeof(object),
        typeof(DependencyPropertyWatcher<T>),
        new PropertyMetadata(
            null,
            (s, e) =>
            {
                var control = s as DependencyPropertyWatcher<T>;
                if (control != null)
                {
                    control.OnValueChanged(control);
                }
            }));

    /// <summary>
    /// 監視対象値 変更イベントハンドラ
    /// </summary>
    private void OnValueChanged(object sender)
    {
        DependencyPropertyWatcher<T> source = (DependencyPropertyWatcher<T>)sender;

        if (source.PropertyChanged != null)
        {
            source.PropertyChanged(source, EventArgs.Empty);
        }
    }

    /// <summary>
    /// 監視対象値
    /// </summary>
    public T Value
    {
        get { return (T)this.GetValue(ValueProperty); }
    }
    #endregion //Value 依存関係プロパティ

    /// <summary>
    /// コンストラクタ
    /// </summary>
    /// <param name="target">監視対象</param>
    /// <param name="propertyPath">監視対象プロパティ</param>
    public DependencyPropertyWatcher(DependencyObject target, string propertyPath)
    {
        this.Target = target;
        BindingOperations.SetBinding(
            this,
            ValueProperty,
            new Binding() { Source = target, Path = new PropertyPath(propertyPath), Mode = BindingMode.OneWay });
    }

    /// <summary>
    /// プロパティ変更イベント
    /// </summary>
    public event EventHandler PropertyChanged;

    /// <summary>
    /// 監視対象
    /// </summary>
    public DependencyObject Target { get; private set; }

    /// <summary>
    /// 破棄処理
    /// </summary>
    public void Dispose()
    {
        this.ClearValue(ValueProperty);
    }
}

監視対象のコントロールと対象となるプロパティのパスを引数にしてコンストラクタで生成すると PropertyChanged のイベントで変更を検知できるようになりました