[Feature] Add Helper Extension `IList<T>.SyncWith(IList<T> another, IEqualityComparer<T> comparer = null)`
Describe the problem
This might not be quite requiring, but it will indeed help a lot in some cases where we need to update the entire list ListViewBase.ItemSource without blinking the UI.
For example:
var data = await SomeDataService.FetchDataAsync() // IList<TDataType>;
var oc = new ObservableCollection<TDataType>(data);
MyListView.ItemSource = oc; // Update the entire list.
Each time we update the entire data list (with data binding or not), the UI will blink, this is not terrible but it would be better if we can have an auto diff tool to make it visually updated with only different elements.
Describe the solution
A helper extension IList<T>.SyncWith(IList<T> another, IEqualityComparer<T> comparer = null) could be an initial idea:
// Implementation
public static IList<TSource> SyncWith<TSource>(
this IList<TSource> source,
IList<TSource> another,
IEqualityComparer<TSource> comparer = null)
{
// Step 1: Remove redundant items, if any.
source.Except(another).ToList().ForEach(x => _ = source.Remove(x));
// Step 2: Update the list, index by index.
for (var index = 0; index < another.Count; index++)
{
var newItem = another[index];
if (index < source.Count)
{
var oldItem = source[index];
if (comparer?.Equals(newItem, oldItem) ?? Equals(newItem, oldItem))
{
continue;
}
// Step 2-1: remove the old item, if it's been changed at the current position.
source.RemoveAt(index);
}
// Step 2-2: insert the new item at the current position.
source.Insert(index, newItem);
}
// Step 3: (last but not least) assertive verification.
Debug.Assert(source.SequenceEqual(another, comparer));
return source;
}
// Use Case
var data = await SomeDataService.FetchDataAsync(); // IList<TDataType>
var oc = new ObservableCollection<TDataType>(data);
MyListView.ItemSource = oc; // Initializes the entire list.
// When we need to update the entire list
data = await SomeDataService.FetchDataAsync(); // IList<TDataType>
_ = oc.SyncWith(data); // The UI won't blink and will apply the corresponding update animations.
Alternatives
No response
Additional info
No response
Help us help you
Yes, I'd like to be assigned to work on this item.
Hello, 'jingkecn! Thanks for submitting a new feature request. I've automatically added a vote 👍 reaction to help get things started. Other community members can vote to help us prioritize this feature in the future!
@Sergio0694 this sounds similar to an example you did in the MVVM Toolkit Sample App, eh?
Moving this to the dotnet repo as a feature request as it deals with IList as the interface vs. anything to a specific framework.
@michael-hawker indeed, I did it with IList to make it as common as possible, thanks for moving it to the dotnet repo.
@michael-hawker Any updates? ☺️