Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom ItemsSource property for a UserControl

Does anyone know how to make a custom ItemsSource?

What I want to do is to make an itemsSource to my own UserControl so that it could be bound by ObservableCollection<>.

Also, I could know Whenever the number of items in the itemsSource updated, so as to do further procedures.

Thank you so much.

like image 991
user1184598 Avatar asked Feb 27 '12 04:02

user1184598


3 Answers

You may need to do something like this in your control

public IEnumerable ItemsSource
{
    get { return (IEnumerable)GetValue(ItemsSourceProperty); }
    set { SetValue(ItemsSourceProperty, value); }
}

public static readonly DependencyProperty ItemsSourceProperty =
    DependencyProperty.Register("ItemsSource", typeof(IEnumerable), typeof(UserControl1), new PropertyMetadata(new PropertyChangedCallback(OnItemsSourcePropertyChanged)));

private static void OnItemsSourcePropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
    var control = sender as UserControl1;
    if (control != null)
        control.OnItemsSourceChanged((IEnumerable)e.OldValue, (IEnumerable)e.NewValue);
}



private void OnItemsSourceChanged(IEnumerable oldValue, IEnumerable newValue)
{
    // Remove handler for oldValue.CollectionChanged
    var oldValueINotifyCollectionChanged = oldValue as INotifyCollectionChanged;

    if (null != oldValueINotifyCollectionChanged)
    {
        oldValueINotifyCollectionChanged.CollectionChanged -= new NotifyCollectionChangedEventHandler(newValueINotifyCollectionChanged_CollectionChanged);
    }
    // Add handler for newValue.CollectionChanged (if possible)
    var newValueINotifyCollectionChanged = newValue as INotifyCollectionChanged;
    if (null != newValueINotifyCollectionChanged)
    {
        newValueINotifyCollectionChanged.CollectionChanged += new NotifyCollectionChangedEventHandler(newValueINotifyCollectionChanged_CollectionChanged);
    }

}

void newValueINotifyCollectionChanged_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
    //Do your stuff here.
}
like image 91
gaurawerma Avatar answered Nov 15 '22 05:11

gaurawerma


Use a DependencyProperty ItemsSource in your CustomControl and then bind to this DependencyProperty

This is the XAML-Code (Recognize the DataContext of the ListBox):

<UserControl
    x:Name="MyControl">
    <ListBox
        DataContext="{Binding ElementName=MyControl}"
        ItemsSource="{Binding ItemsSource}">
    </ListBox>
</UserControl>

This is the CodeBehind:

public partial class MyCustomControl
{
    public IEnumerable ItemsSource
    {
        get { return (IEnumerable)GetValue(ItemsSourceProperty); }
        set { SetValue(ItemsSourceProperty, value); }
    }

    public static readonly DependencyProperty ItemsSourceProperty =
        DependencyProperty.Register("ItemsSource", typeof(IEnumerable),
            typeof(ToolboxElementView), new PropertyMetadata(null));
}

This is the Code, where you use your "MyCustomControl":

<Window>
    <local:MyCustomControl
        ItemsSource="{Binding MyItemsIWantToBind}">
    </local:MyCustomControl>
</Window>
like image 37
Alex Avatar answered Nov 15 '22 04:11

Alex


Simplified answer.

    public IEnumerable ItemsSource
    {
        get => (IEnumerable)GetValue(ItemsSourceProperty);
        set => SetValue(ItemsSourceProperty, value);
    }

    public static readonly DependencyProperty ItemsSourceProperty =
        DependencyProperty.Register("ItemsSource", typeof(IEnumerable), typeof(UserControl1), new PropertyMetadata(null, (s, e) =>
        {
            if (s is UserControl1 uc)
            {
                if (e.OldValue is INotifyCollectionChanged oldValueINotifyCollectionChanged)
                {
                    oldValueINotifyCollectionChanged.CollectionChanged -= uc.ItemsSource_CollectionChanged;
                }

                if (e.NewValue is INotifyCollectionChanged newValueINotifyCollectionChanged)
                {
                    newValueINotifyCollectionChanged.CollectionChanged += uc.ItemsSource_CollectionChanged;
                }
            }
        }));

    private void ItemsSource_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        // Logic Here
    }

    // Do Not Forget To Remove Event On UserControl Unloaded
    private void UserControl1_Unloaded(object sender, RoutedEventArgs e)
    {
        if (ItemsSource is INotifyCollectionChanged incc)
        {
            incc.CollectionChanged -= ItemsSource_CollectionChanged;
        }
    }
like image 1
Egemen Çiftci Avatar answered Nov 15 '22 05:11

Egemen Çiftci