I am programming an app in WinUI 3 using C#.
There are some controls that have an ItemsSource property.
When I pass an IEnumerable into the ItemsSource and then change the IEnumerable, the control changes accordingly.
I now want to implement the same behavior in my custom UserControl.
I have the following code, but it only works with IEnumerables that implement INotifyCollectionChanged (eg. ObservableCollection).
WinUI supports IEnumerables that don't implement INotifyCollectionChanged.
How can I do the same?
Here is my code:
public sealed partial class MyUserControl : UserControl
{
public static readonly DependencyProperty ItemsSourceProperty =
DependencyProperty.Register("ItemsSource", typeof(IEnumerable), typeof(MyUserControl), new PropertyMetadata(null));
public IEnumerable ItemsSource
{
get { return (IEnumerable)GetValue(ItemsSourceProperty); }
set { SetValue(ItemsSourceProperty, value); }
}
private IEnumerable _oldItemsSource;
public MyUserControl()
{
this.InitializeComponent();
RegisterPropertyChangedCallback(ItemsSourceProperty, OnItemsSourceChanged);
}
private void OnItemsSourceChanged(DependencyObject sender, DependencyProperty prop)
{
if (prop == ItemsSourceProperty)
{
var newValue = (IEnumerable)sender.GetValue(ItemsSourceProperty);
if (_oldItemsSource is INotifyCollectionChanged oldCollection)
{
oldCollection.CollectionChanged -= OnCollectionChanged;
}
if (newValue is INotifyCollectionChanged collection)
{
collection.CollectionChanged += OnCollectionChanged;
}
_oldItemsSource = ItemsSource;
}
}
private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
// Update the control here
}
}
WinUI 3 allows me to use a List (doesn't implement INotifyCollectionChanged) as an ItemsSource.
Changes made to the List affect the control.
This is the code inside a test page:
public TestPage()
{
this.InitializeComponent();
var list = new List<string> { "Item1", "Item2", "Item3" };
var bar = new BreadcrumbBar(); ;
bar.ItemsSource = list;
this.Content = bar;
list.Add("Item4");
// The BreadcrumbBar now has 4 elements.
}