3

DependencyPropertyと対応するコールバックメソッドを使用した独自のユーザーコントロールがある場合は、次のようになります。

public partial class PieChart : UserControl
{
    public static readonly DependencyProperty RatesProperty = DependencyProperty.Register("Rates", typeof(ObservableCollection<double>), typeof(PieChart),
        new PropertyMetadata(new ObservableCollection<double>() { 1.0, 1.0 }, new PropertyChangedCallback(OnRatesChanged)));

[...]

    public static void OnRatesChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        ((PieChart)d).drawChart();
    }

このユーザーコントロールを使用するときは、「Rates」というObservableCollectionをRatesPropertyにバインドします。料金と関連する方法は次のようになります。

private ObservableCollection<double> rates;
public ObservableCollection<double> Rates
{
    get { return this.rates; }
    set
    {
        if (this.rates != value)
        {
            this.rates = value;
            OnPropertyChanged("Rates");
        }
    }
}

public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
    if (PropertyChanged != null)
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}

ObservableCollectionレートを変更すると(たとえば、を使用してthis.Rates = new ObservableCollection<double>() { 1.0, 2.0 })、ユーザーコントロールのOnRatesChanged()メソッドが期待どおりに呼び出されます。しかし、私が以下を実行するとき、それは呼び出されません:

this.Rates[0] = (double)1;
this.Rates[1] = (double)2;
OnPropertyChanged("Rates");

正しいプロパティ名でPropertyChangedイベントを発生させると、ユーザーコントロールの対応するコールバックが常に呼び出されることを期待していました。それは間違っていますか?私はこのスレッドを見つけました:依存関係プロパティのPropertyChangedCallbackを常に取得する -SilverlightをカバーするSilverlightですが、WPFでも同じことが当てはまると思います。

したがって、バックグラウンドのフレームワークは、バインドされたプロパティ(私の例では「Rates」)が変更されたかどうかをチェックし、変更された場合にのみ、関連するコールバックを呼び出します。したがって、コレクションの要素を変更しても効果はありません。コレクション全体を常に変更する必要がありますか?

ありがとうございました!

4

1 に答える 1

6

結論は正しいです。コールバックは、依存関係プロパティが新しいコレクション(またはnull)に設定されているOnRatesChanged場合にのみ呼び出されます。Rates

コレクションの変更に関する通知を受け取るには、NotifyCollectionChangedEventHandlerも登録する必要があります。

private static void OnRatesChanged(
    DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    var pieChart = (PieChart)d;
    var oldRates = e.OldValue as INotifyCollectionChanged;
    var newRates = e.NewValue as INotifyCollectionChanged;

    if (oldRates != null)
    {
        oldRates.CollectionChanged -= pieChart.OnRatesCollectionChanged;
    }

    if (newRates != null)
    {
        newRates.CollectionChanged += pieChart.OnRatesCollectionChanged;
    }

    pieChart.drawChart();
}

private void OnRatesCollectionChanged(
    object sender, NotifyCollectionChangedEventArgs e)
{
    switch (e.Action)
    {
        ...
    }

    drawChart();
}
于 2012-10-05T13:03:09.043 に答える