在previous post中,我问过如何将属性注册为DependencyProperty。我得到了答案,它工作正常。
但是现在我想在Click上为这个DependencyProperty添加一些Items。这不起作用。我注册DependencyProperty的代码是:
public static readonly DependencyProperty ChartEntriesProperty = DependencyProperty.Register(
"ChartEntries", typeof(ObservableCollection<ChartEntry>), typeof(ChartView),
new FrameworkPropertyMetadata(OnChartEntriesChanged));
private static void OnChartEntriesChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
}
在我从XAML绑定到我的c#-code时,会调用OnChartEntriesChanged-Event。但是如果我之后添加ChartEntry(按下按钮),则不会触发事件。
有谁知道为什么?
答案 0 :(得分:5)
当您将项目添加到ChartEntries
集合时, 实际上不会更改该属性,因此不会调用PropertyChangedCallback。为了获得有关集合中更改的通知,您需要注册一个额外的CollectionChanged
事件处理程序:
private static void OnChartEntriesChanged(
DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
var chartView = (ChartView)obj;
var oldCollection = e.OldValue as INotifyCollectionChanged;
var newCollection = e.NewValue as INotifyCollectionChanged;
if (oldCollection != null)
{
oldCollection.CollectionChanged -= chartView.OnChartEntriesCollectionChanged;
}
if (newCollection != null)
{
newCollection.CollectionChanged += chartView.OnChartEntriesCollectionChanged;
}
}
private void OnChartEntriesCollectionChanged(
object sender, NotifyCollectionChangedEventArgs e)
{
...
}
不使用ObservableCollection<ChartEntry>
作为属性类型也是有意义的,而只是ICollection
或IEnumerable
。这将允许具体集合类型中的INotifyCollectionChanged
的其他实现。有关详细信息,请参阅here和here。
答案 1 :(得分:1)
OnChartEntriesChanged
的新实例时,将调用 ObservableCollection
回调。您将不得不听取如下更改的集合:
private static void OnChartEntriesChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((ObservableCollection<ChartView>)e.OldValue).CollectionChanged -= new System.Collections.Specialized.NotifyCollectionChangedEventHandler(ChartView_CollectionChanged);
((ObservableCollection<ChartView>)e.NewValue).CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(ChartView_CollectionChanged);
}
static void ChartView_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
}
答案 2 :(得分:0)
很抱歉,但这不会有效,因为您已经检测到了自己。如果属性的值发生更改,则DependencyProperty更改的处理程序仅触发,但在您的情况下则不会,因为对象引用仍然相同。您必须在提供的集合的CollectionChanged事件处理程序上注册。 (这可以在dependencyproperty的propertychanged处理程序中完成)
答案 3 :(得分:0)
Clemens的答案看起来不错,对我有很大帮助。但是,在很多情况下,当整个集合被另一个集合替换时,您也希望您的CollectionChanged事件处理程序也被调用。为此,只需直接从PropertyChanged事件处理程序中显式直接调用CollectionChanged事件处理程序即可。完整的代码如下所示。
private static void OnChartEntriesChanged(
DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
var chartView = (ChartView)obj;
var oldCollection = e.OldValue as INotifyCollectionChanged;
var newCollection = e.NewValue as INotifyCollectionChanged;
if (oldCollection != null)
{
oldCollection.CollectionChanged -= chartView.OnChartEntriesCollectionChanged;
}
if (newCollection != null)
{
newCollection.CollectionChanged += chartView.OnChartEntriesCollectionChanged;
}
// The first parameter below can also be null
chartView.OnChartEntriesCollectionChanged(newCollection, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
private void OnChartEntriesCollectionChanged(
object sender, NotifyCollectionChangedEventArgs e)
{
...
}