Property Changed in DependencyProperty

半世苍凉 提交于 2019-12-17 17:11:35

问题


In a previous post I asked how to register a property as DependencyProperty. I got an answer and it works fine.

But now I want to add some Items to this DependencyProperty on a Click. This doesn't work. My code to register the DependencyProperty is:

public static readonly DependencyProperty ChartEntriesProperty = DependencyProperty.Register(
        "ChartEntries", typeof(ObservableCollection<ChartEntry>), typeof(ChartView),
        new FrameworkPropertyMetadata(OnChartEntriesChanged));

    private static void OnChartEntriesChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {

    }

The OnChartEntriesChanged-Event is called at the moment I do the Binding from my XAML to my c#-code. But if I add a ChartEntry afterwards (on button-click) the event is not fired.

Does anyone know why?


回答1:


When you add an item to the ChartEntries collection, you do not actually change that property, so the PropertyChangedCallback isn't called. In order to get notified about changes in the collection, you need to register an additional CollectionChanged event handler:

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

It would also make sense not to use ObservableCollection<ChartEntry> for the property type, but simply ICollection or IEnumerable instead. This would allow for other implementations of INotifyCollectionChanged in the concrete collection type. See here and here for more information.




回答2:


OnChartEntriesChanged callback will be called when you will set the new instance of the ObservableCollection. You will have to listen to collection changed as below:

    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)
    {

    }



回答3:


Sorry but this won't work as you've detected yourself. The DependencyProperty changed handler does fire only, if the value of the property changes, but in your case it doesn't, as the object reference is still the same. You have to register on the CollectionChanged eventhandler of the provided collection. (this you can do in the propertychanged handler from the dependencyproperty)




回答4:


The answer from Clemens looks good and helped me a lot. However, in many cases you will want your CollectionChanged event handler to get called also when the entire collection is replaced with another collection. To do this, simply call the CollectionChanged event handler explicitly and directly from the PropertyChanged event handler. The full code would look as follows.

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


来源:https://stackoverflow.com/questions/19558862/property-changed-in-dependencyproperty

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!