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 Rates(例如使用this.Rates = new ObservableCollection<double>() { 1.0, 2.0 })时,用户控件的 OnRatesChanged() 方法会像预期的那样被调用。但是当我执行以下命令时,它不会被调用:

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

我希望当我使用正确的属性名称引发 PropertyChanged 事件时,始终会调用用户控件中的相应回调。那是错的吗?我找到了这个线程:Getting PropertyChangedCallback of a dependency property always - 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 回答