ArgumentOutOfRangeException when replacing elements in ObservableCollection <T>
I am working on an extension of the Refresh () method for the ObservableCollection, which adds, removes or replaces elements based on the corresponding key (this means that when binding to the DataGrid, the grid does not re-scroll and the elements do not change their position if they were not deleted).
The problem is when I replace the elements in an ObservableCollection, the last element throws an ArgumentOutOfRangeException, what am I missing here?
public static void Refresh<TItem, TKey>(this ObservableCollection<TItem> target, IEnumerable<TItem> source, Func<TItem, TKey> keySelector) { var sourceDictionary = source.ToDictionary(keySelector); var targetDictionary = target.ToDictionary(keySelector); var newItems = sourceDictionary.Keys.Except(targetDictionary.Keys).Select(k => sourceDictionary[k]).ToList(); var removedItems = targetDictionary.Keys.Except(sourceDictionary.Keys).Select(k => targetDictionary[k]).ToList(); var updatedItems = (from eachKey in targetDictionary.Keys.Intersect(sourceDictionary.Keys) select new { Old = targetDictionary[eachKey], New = sourceDictionary[eachKey] }).ToList(); foreach (var updatedItem in updatedItems) { int index = target.IndexOf(updatedItem.Old); target[index] = updatedItem.New; // ArgumentOutOfRangeException is thrown here } foreach (var removedItem in removedItems) { target.Remove(removedItem); } foreach (var newItem in newItems) { target.Add(newItem); } } +3
1 answer
You have old and new, vice versa. It:
var updatedItems = (from eachKey in targetDictionary.Keys .Intersect(sourceDictionary.Keys) select new { Old = targetDictionary[eachKey], New = sourceDictionary[eachKey] }).ToList(); should be as follows:
var updatedItems = (from eachKey in targetDictionary.Keys .Intersect(sourceDictionary.Keys) select new { New = targetDictionary[eachKey], Old = sourceDictionary[eachKey] }).ToList(); You are currently looking for the index of a new value that will be -1 ...
+2