public class Alpha
{
public ObservableCollection<Beta> Items { get; set; }
public Alpha()
{
Items = new ObservableCollection<Beta>();
}
public void DoSomething()
{
Items = GetNewItems(); // whenever I do this, Items gets a new referene,
// so every WPF binding (e.g. datagrids) are broken
}
public ObservableCollection<Beta> GetNewItems()
{
var ret = new ObservableCollection<Beta>();
// some logic for getting some items from somewhere, and populating ret
return ret;
}
}
How can I replace the whole content of Items
with the return value of GetNewItems()
without:
Breaking the bindings.
Having to loop through the items and copy them one by one to the other collection ?
You have some options:
BindingOperations.EnableCollectionSynchronization
. Recommended
Numbers 2 and 3, with respect to your question, translate to clearing the existing items (Clear()) and then adding (Add()) the items returned by whatever method you want - see the example for #3. They key is that the clearing and all of the adding must be done with Dispatcher (2) or by calling BindingOperations.EnableCollectionSynchronization
.
Good luck!
Reference: Reed Copsey Answer - StackOverflow
ObservableCollection implements INotifyCollectionChanged, which will update bindings whenever items get added or removed. All that is needed here is to clear the list for the CollectionChanged event to fire.
public void GetNewItems()
{
Items.Clear();
// some logic for getting some items from somewhere, and populating ret
}
You can also make your own class that will extend the ObservableCollection, here is an example with notifications sorted:
https://github.com/jamesmontemagno/mvvm-helpers/blob/master/MvvmHelpers/ObservableRangeCollection.cs
I'm using simpler implementation of above (I did not compared the notification aspect yet):
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using BaseLibrary.Properties;
namespace BaseLibrary
{
/// <summary>
/// Represents a dynamic data collection that provides notifications when items get added, removed, or when the whole list is refreshed.
/// </summary>
/// <typeparam name="T"></typeparam>
public class ObservableCollectionEx<T> : ObservableCollection<T>
{
//INotifyPropertyChanged interited from ObservableCollection<T>
#region INotifyPropertyChanged
protected override event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
public void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion INotifyPropertyChanged
/// <summary>
/// Adds the elements of the specified collection to the end of the ObservableCollection(Of T).
/// </summary>
public void AddRange(IEnumerable<T> collection)
{
if (collection == null) throw new ArgumentNullException(nameof(collection));
foreach (var i in collection) Items.Add(i);
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
/// <summary>
/// Removes the first occurence of each item in the specified collection from ObservableCollection(Of T).
/// </summary>
public void RemoveRange(IEnumerable<T> collection)
{
if (collection == null) throw new ArgumentNullException(nameof(collection));
foreach (var i in collection) Items.Remove(i);
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
/// <summary>
/// Clears the current collection and replaces it with the specified item.
/// </summary>
public void Replace(T item)
{
Replace(new T[] { item });
}
/// <summary>
/// Replaces all elements in existing collection with specified collection of the ObservableCollection(Of T).
/// </summary>
public void Replace(IEnumerable<T> collection)
{
if (collection == null) throw new ArgumentNullException(nameof(collection));
Items.Clear();
foreach (var i in collection) Items.Add(i);
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
/// <summary>
/// Initializes a new instance of the System.Collections.ObjectModel.ObservableCollection(Of T) class.
/// </summary>
public ObservableCollectionEx()
: base() { }
/// <summary>
/// Initializes a new instance of the System.Collections.ObjectModel.ObservableCollection(Of T) class that contains elements copied from the specified collection.
/// </summary>
/// <param name="collection">collection: The collection from which the elements are copied.</param>
/// <exception cref="System.ArgumentNullException">The collection parameter cannot be null.</exception>
public ObservableCollectionEx(IEnumerable<T> collection)
: base(collection) { }
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With