I would like to re-render my WPF chart control when data source is changed. My minimum requirement for a data source is `IEnumerable<Point>` but it could be also `ObservableCollection<Point>` or `BindingList<Point>`, so collection change notifications are sometimes becoming available.

Chart `Serie` class (simplified):

```
class Serie : Freezable
{
    public static readonly DependencyProperty DataProperty =
        DependencyProperty.Register("Data", typeof(IEnumerable<Point>), typeof(Serie));

    public Serie()
    {
        new ChangeListner(this, DataProperty);
    }

    public IEnumerable<Point> Data
    {
        get { return (IEnumerable<Point>)GetValue(DataProperty); }
        set { SetValue(DataProperty, value); }
    }

    public void Draw(DrawingContext drawingContext)
    {
        if (Data == null)
            return;

        foreach (var point in Data)
            drawingContext.DrawEllipse(Brushes.Black, null, point, 4, 4);
    }

    protected override Freezable CreateInstanceCore() => new Serie();
}

```

Where notifications are being monitored by (real code):

```
class ChangeListner
{
    public ChangeListner(Freezable subject, DependencyProperty property)
    {
        Subject = subject;
        Property = property;
        DependencyPropertyDescriptor
            .FromProperty(property, subject.GetType())
            .AddValueChanged(subject, OnChanged);
    }

    private void OnChanged(object sender, EventArgs e)
    {
        var value = Subject.GetValue(Property);
        BindingList = value as IBindingList;
        NotifyCollectionChanged = value as INotifyCollectionChanged;
        NotifyPropertyChanged = value as INotifyPropertyChanged;
    }

    Freezable Subject { get; }
    DependencyProperty Property { get; }

    INotifyPropertyChanged _notifyPropertyChanged;
    INotifyPropertyChanged NotifyPropertyChanged
    {
        set
        {
            if (_notifyPropertyChanged != null)
                _notifyPropertyChanged.PropertyChanged -= _notifyPropertyChanged_CollectionChanged;

            _notifyPropertyChanged = value;

            if (_notifyPropertyChanged != null)
                _notifyPropertyChanged.PropertyChanged += _notifyPropertyChanged_CollectionChanged;
        }
    }
    void _notifyPropertyChanged_CollectionChanged(object sender, PropertyChangedEventArgs e) =>
        Notify();

    INotifyCollectionChanged _notifyCollectionChanged;
    INotifyCollectionChanged NotifyCollectionChanged
    {
        set
        {
            if (_notifyCollectionChanged != null)
                _notifyCollectionChanged.CollectionChanged -= _notifyCollectionChanged_CollectionChanged;

            _notifyCollectionChanged = value;

            if (_notifyCollectionChanged != null)
                _notifyCollectionChanged.CollectionChanged += _notifyCollectionChanged_CollectionChanged;
        }
    }
    void _notifyCollectionChanged_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) =>
        Notify();

    IBindingList _bindingList;
    IBindingList BindingList
    {
        set
        {
            if (_bindingList != null)
                _bindingList.ListChanged -= _bindingList_ListChanged;

            _bindingList = value;

            if (_bindingList != null)
                _bindingList.ListChanged += _bindingList_ListChanged;
        }
    }
    void _bindingList_ListChanged(object sender, ListChangedEventArgs e) =>
        Notify();

    void Notify() => Subject
        .GetType()
        .GetMethod("NotifySubPropertyChange", BindingFlags.Instance | BindingFlags.NonPublic)
        .Invoke(Subject, new[] { Property });
}

```

I am not quite sure about this `Notify` method – reflection invocation is slow and dangerous. Is there a better way to make `Freezable` pickup changes?

Here is the custom control code I use for testing:

```
class Plot : Control
{
    public static readonly DependencyProperty SeriesProperty =
        DependencyProperty.Register("Series", typeof(FreezableCollection<Serie>), typeof(Plot),
            new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender));

    public Plot()
    {
        Series = new FreezableCollection<Serie>();
    }

    public FreezableCollection<Serie> Series
    {
        get { return (FreezableCollection<Serie>)GetValue(SeriesProperty); }
        set { SetValue(SeriesProperty, value); }
    }

    protected override void OnRender(DrawingContext drawingContext)
    {
        base.OnRender(drawingContext);
        if (Series == null)
            return;

        foreach (var serie in Series)
            serie.Draw(drawingContext);
    }
}

```