Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DependencyProperty getter/setter not being called

I am trying to create a Custom control derived from a standard Grid. I added a ObservableCollection as a DependencyProperty of the Custom control. However, the get/set of it is never reached. Can I have some guidelines in creating a DependencyProperty that works correctly with and ObservableCollection?

public class MyGrid : Grid
{
    public ObservableCollection<string> Items
    {
        get
        {
            return (ObservableCollection<string>)GetValue(ItemsProperty);
        }
        set
        {
            SetValue(ItemsProperty, value);
        }
    }

public static  DependencyProperty ItemsProperty =
                DependencyProperty.Register("Items", typeof(ObservableCollection<string>), 
        typeof(MyGrid), new UIPropertyMetadata(null, OnItemsChanged));

}
like image 253
phm Avatar asked Dec 10 '22 02:12

phm


1 Answers

I would suggest not to use ObservableCollection as the type of an Items dependency property.

The reason for having an ObservableCollection here (I guess) is to enable the UserControl to attach a CollectionChanged handler when the property value is assigned. But ObservableCollection is too specific.

The approach in WPF (e.g. in ItemsControl.ItemsSource) is to define a very basic interface type (like IEnumerable) and when the property is assigned a value, find out if the value collection implements certain more specific interfaces. This would at least be INotifyCollectionChanged here, but the collection might also implement ICollectionView and INotifyPropertyChanged. All these interfaces wouldn't be mandatory and that would enable your dependency property to bind to all sorts of collections, starting with a plain array up to a complex ItemCollection.

Your OnItemsChanged property change callback would then look like this:

private static void OnItemsChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
    MyGrid grid = obj as MyGrid;

    if (grid != null)
    {
        var oldCollectionChanged = e.OldValue as INotifyCollectionChanged;
        var newCollectionChanged = e.NewValue as INotifyCollectionChanged;

        if (oldCollectionChanged != null)
        {
            oldCollectionChanged.CollectionChanged -= grid.OnItemsCollectionChanged;
        }

        if (newCollectionChanged != null)
        {
            newCollectionChanged.CollectionChanged += grid.OnItemsCollectionChanged;

            // in addition to adding a CollectionChanged handler
            // any already existing collection elements should be processed here
        }
    }
}

private void OnItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
    // handle collection changes here
}
like image 78
Clemens Avatar answered Dec 27 '22 03:12

Clemens