如果拥有一个带有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 Rate(例如,使用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”)是否发生了变化,只有当它发生变化时才调用相关的回调,对吗?因此改变我的收藏元素没有任何效果,我总是要改变完整的收藏?
谢谢!
您的结论是正确的,只有在将rates依赖项属性设置为新集合(或null)时,才会调用OnRatesChanged回调.
为了获得有关集合更改的通知,您还必须注册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(); }