سؤال

I like to share a list between an application and a custom Usercontrol. I use an IEnumerable as attached property to provide a list to a Listbox inside the custom UserControl. The ListBox then receives the attached property as ItemsSource. This works so far. But when the host list changes, the list inside the usercontrol should get updated. How can I achieve this ? The current code sets the Usercontrol list, but when the host changes the list, the attached property won't get updated.

The host that uses the UserControl has a ComboBox, which should share its ItemsSource with the UserControl's ListBox

public ObservableCollection<Person> PersonList
    {
        get;
        set;
    }

The host's Xaml binds a ComboBox to the collection:

<ComboBox x:Name="combobox1" Width="200" ItemsSource="{Binding PersonList}" DisplayMemberPath="Name" SelectedIndex="0" IsEditable="True"></ComboBox>

The Usercontrol which is placed inside the host receives the collection via attached property. The binding looks heavy but seems ok:

<myUserCtrl:AdvEditBox
    ...
prop:DynamicListProvider.DynamicList="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}},
                        Path=DataContext.PersonList}">
    ...
</myUserCtrl:AdvEditBox

The attached property has a callback, which currently gets called only once:

class DynamicListProvider : DependencyObject
{
    public static readonly DependencyProperty DynamicListProperty = DependencyProperty.RegisterAttached(
       "DynamicList",
       typeof(IEnumerable),
       typeof(DynamicListProvider),
       new FrameworkPropertyMetadata(null, OnDynamicListPropertyChanged)));

    public static IEnumerable GetDynamicList(UIElement target) {..}

    public static void SetDynamicList(UIElement target, IEnumerable value) {..}

    private static void OnDynamicListPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
    {
        if (e.NewValue != null && o is FrameworkElement)
        {
          ...
        }
    }

The OnDynamicListPropertyChanged() should be called whenever the PersonList of the host changes. Do I have to put INotifyCollectionChanged inside the attached property? If so, where and how ?

هل كانت مفيدة؟

المحلول

here's my solution:

1) the usercontrol's dp:

public static readonly DependencyProperty SelectionListProperty = DependencyProperty.Register(
        "SelectionList",
        typeof(ObservableCollection<MyList>),
        typeof(MyUserControl),
        new UIPropertyMetadata(null));

(..add property get/set wrapper)

2) set your UserControls ItemsSource on the List, e.g.

_combobox.ItemsSource = SelectionList;

3) the host owns the list. Add the data and its property in the class which instantiates the usercontrol. In my case, I use readonly / oneway binding.

ObservableCollection<MyList> _bigList= new ObservableCollection<MyList>();
public ObservableCollection<MyList> BigList
    {
        get { return _bigList; }
    }

4) set binding in xaml

<myctrl:MyUserControl
    SelectionList="{Binding BigList, Mode=OneWay}"
     ...
 />

5) Now whenever you modify the _biglist, call your PropertyChangedEventHandler on "BigList". This will notify the UserControl's SelectionList as set by the binding and call the BigList get{}. Hope it's clear to you.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top