user2516186
user2516186

Reputation: 483

Binding to custom Dependency Property fails

As the SelectedItems property of the ListBox control is a normal property and not a dependency property to bind to, I have derived of the ListBox and created a new dependency property SelectedItemsEx.

But my XAML compiler keeps giving me the error

A 'Binding' cannot be set on the 'SelectedItemsEx' property of the type 'MyListBox'. A 'Binding' can only be set on a DependencyProperty of a DependencyObject.

Why my property is not recognized as a dependency property? Any help is appreciated, thank you!

XAML:

  <MyListBox ItemsSource="{Binding MyData}" SelectedItemsEx="{Binding SelectedEx}" 
                                            SelectionMode="Extended"> ... </MyListBox>

ListBox' implementation:

public class MyListBox : ListBox
{
    public readonly DependencyProperty SelectedItemsExProperty =
            DependencyProperty.Register("SelectedItemsEx", 
                typeof(ObservableCollection<MyItemsDataType>), 
                typeof(MyListBox), 
                new PropertyMetadata(default(ObservableCollection<MyItemsDataType>)));


    public ObservableCollection<MyItemsDataType> SelectedItemsEx
    {
        get
        {
            var v = GetValue(SelectedItemsExProperty);
            return (ObservableCollection<MyItemsDataType>)v;
        }
        set { SetValue(SelectedItemsExProperty, value); }
    }

    protected override void OnSelectionChanged(SelectionChangedEventArgs e)
    {
        base.OnSelectionChanged(e);
        if (SelectedItemsEx != null)
        {
            SelectedItemsEx.Clear();
            foreach (var item in base.SelectedItems)
            {
                SelectedItemsEx.Add((MyItemsDataType)item);
            }
        }
    }

Upvotes: 0

Views: 920

Answers (1)

Clemens
Clemens

Reputation: 128136

The DependencyProperty field must be static:

public static readonly DependencyProperty SelectedItemsExProperty = ...

Note also that in order to make your derived ListBox a little more reusable, you should not constrain the type of the SelectedItemsEx property. Use IEnumerable (or IList like SelectedItems) instead. Moreover, there is no need to specify a default value by property metadata, as it is null already and default(<any reference type>) is also null.

You will however have to get notified whenever the SelectedItemsEx property has changed. Therefore you have to register a change callback via property metadata:

public static readonly DependencyProperty SelectedItemsExProperty =
    DependencyProperty.Register(
        "SelectedItemsEx", typeof(IEnumerable), typeof(MyListBox),
        new PropertyMetadata(SelectedItemsExPropertyChanged));

public IEnumerable SelectedItemsEx
{
    get { return (IEnumerable)GetValue(SelectedItemsExProperty); }
    set { SetValue(SelectedItemsExProperty, value); }
}

private static void SelectedItemsExPropertyChanged(
    DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
    var listBox = (MyListBox)obj;
    var oldColl = e.OldValue as INotifyCollectionChanged;
    var newColl = e.NewValue as INotifyCollectionChanged;

    if (oldColl != null)
    {
        oldColl.CollectionChanged -= listBox.SelectedItemsExCollectionChanged;
    }

    if (newColl != null)
    {
        newColl.CollectionChanged += listBox.SelectedItemsExCollectionChanged;
    }
}

private void SelectedItemsExCollectionChanged(
    object sender, NotifyCollectionChangedEventArgs e)
{
    switch (e.Action)
    {
        ...
    }
}

Upvotes: 3

Related Questions