属性在DependencyProperty中更改

时间:2013-10-24 06:46:24

标签: c# wpf dependency-properties

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(按下按钮),则不会触发事件。

有谁知道为什么?

4 个答案:

答案 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>作为属性类型也是有意义的,而只是ICollectionIEnumerable。这将允许具体集合类型中的INotifyCollectionChanged的其他实现。有关详细信息,请参阅herehere

答案 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)
{
    ...
}