4

依存関係プロパティを利用する WPF のビジュアル コントロールがあります。これらのプロパティは、クラスであるフィールドによってサポートされており、含まれているクラスが実際に変更されたときに、プロパティの値が変更されたことをすべてのバインディングに通知する必要がある場合があります。

簡単に言った:

  • MyDepProp は MyClass 型です。
  • MyClass の内容は、コントロールの内部操作によって変更されます。
  • MyDepProp が変更され、MyClass の変更を反映できるように、皆さんにお知らせしたいと思います。

MSDN によると、依存関係プロパティが初めて使用されるときに、PropertyChanged が DependencyObject にアタッチされます。Visual Studio 2010 で動作します。ただし、Visual Studio 2012 をインストールした後、動作しなくなりました。DP が使用されていても (たとえば、バインディングがアタッチされていても)、PropertyChanged は null であり、変更を誰にも通知できません。

私はまだVisual Studio 2010コンパイラツールキットを使用しているので、VS 2012とともに更新された壊れたフレームワークの問題のようです.

PropertyChanged イベントを正しく使用していますか? それとも、VS 2012 によって更新された .NET 4.0 フレームワークのバグですか? 誰かが同様の問題に遭遇しましたか?


編集:バグのあるコードの一部:

public partial class MyImageControl : INotifyPropertyChanged,
    IHandle<ImageRefresh>
{
    // ***************************
    // *** Dependency property ***
    // ***************************

    private void OnDataSourceChanged()
    {
        // ...
    }

    private static void DataSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (d is MyImageControl)
            ((MyImageControl)d).OnDataSourceChanged();
    }

    public static readonly DependencyProperty DataSourceProperty = DependencyProperty.Register("DataSource",
        typeof(IDataSource),
        typeof(MyImageControl),
        new PropertyMetadata(null, DataSourceChanged));

    public IDataSource DataSource
    {
        get
        {
            return (IDataSource)GetValue(DataSourceProperty);
        }

        set
        {
            SetCurrentValue(DataSourceProperty, value);
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs("DataSource"));
        }
    }

    // ***********************************
    // *** INotifyPropertyChanged impl ***
    // ***********************************

    public event PropertyChangedEventHandler PropertyChanged;

    // *************************************
    // *** Method, which exposes the bug ***
    // *************************************

    public void Handle(ImageRefresh message)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs("BackgroundKind"));
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs("DataSource"));
    }
}

参考までに、IHandle インターフェイスは次のとおりです。

public interface IBaseHandle { }

public interface IHandle<TMessage> : IBaseHandle
{
    void Handle(TMessage message);
}

シナリオ:

  • DataSourceBinding
  • 誰かがHandleコントロールのメソッドを呼び出します (IHandleインターフェースを使用)
  • PropertyChanged が null ではないかどうかのチェックを処理するため、DataSource の変更に関する情報は伝達されません。
4

1 に答える 1

1

まず、このコードは冗長です。

            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs("DataSource"));

WPF DP システムはセッターやゲッターを使用せずに DP に直接アクセスするため、通常のプロパティ セッターに追加のコードを記述することはお勧めしません。PropertyChangedメソッドで上げOnDataSourceChangedます。

次に、コントロールDependencyObjectは依存プロパティを追加できるものを継承します。
更新により以前の動作が変更され、DP システムがコントロールの Dependency プロパティにバインドするときに、ProprtyChanged イベントを介して通知をサブスクライブしない可能性があります。これは、その必要がないためです。DP システムには通知があります。それがnull
である理由である可能性があります。PropertyChanged

アップデート

このように CurrentValue を設定すると、微妙なバグが発生する可能性があると思います。通常SetCurrentValue()、内部的な理由により値を変更する必要がある場合に使用されます。たとえば、ユーザーがテキストを入力したときにプロパティ値をTextBox設定します。これにより、バインディングを保存できます。 しかし、バインディングをプログラムで設定しようとするとどうなるでしょうか?TextSetCurrentValue()

あなたが試すことができるコメントであなたが言ったことによると:

  • 値を null に設定してから元に戻します。
  • INotifyPropertyChangedDataSource の実装
  • 電話DependencyObject.InvalidateProperty()
于 2013-03-28T11:24:02.287 に答える