dotnet/wpf · error · NotSupportedException
SR.RangeActionsNotSupported
Error message
SR.RangeActionsNotSupported
What it means
ItemContainerGenerator's OnCollectionChanged only supports single-item Add and Remove notifications. If an event reports multiple items (NewItems.Count or OldItems.Count != 1) for those actions, it throws NotSupportedException SR.RangeActionsNotSupported, because range change actions are not supported by this generator's incremental update logic.
Solutions
- Raise one Add/Remove event per item instead of a multi-item range event.
- Raise NotifyCollectionChangedAction.Reset for bulk changes so the generator rebuilds.
- Replace custom AddRange with sequential Add calls, or use a collection that emits Reset on bulk operations.
Example fix
// before
OnCollectionChanged(new NotifyCollectionChangedEventArgs(Add, newItemsList, startIndex)); // multi-item
// after
foreach (var item in newItemsList)
{
items.Add(item);
OnCollectionChanged(new NotifyCollectionChangedEventArgs(Add, item, items.IndexOf(item)));
}
// or: OnCollectionChanged(new NotifyCollectionChangedEventArgs(Reset)); Defensive patterns
Strategy: validation
Validate before calling
// Guard in your collection wrapper before raising:
if (action == NotifyCollectionChangedAction.Add && args.NewItems.Count != 1)
throw new NotSupportedException("ItemContainerGenerator supports only single-item Add; use Reset for bulk changes"); Type guard
static bool IsSingleItemChange(NotifyCollectionChangedEventArgs a) =>
(a.Action == NotifyCollectionChangedAction.Add && a.NewItems.Count == 1) ||
(a.Action == NotifyCollectionChangedAction.Remove && a.OldItems.Count == 1); Try / catch
try { /* bind collection */ }
catch (NotSupportedException) { /* replace source with a Reset-emitting adapter */ } Prevention
- Never raise multi-item Add/Remove events toward ItemContainerGenerator.
- Implement AddRange as sequential single-item Adds or a final Reset.
- Wrap third-party range-event collections in an adapter that emits Reset.
When it happens
Trigger: A source INotifyCollectionChanged collection raises Add or Remove with several items at once (multi-item range events), e.g. AddRange-like extensions that batch notifications.
Common situations: Custom ObservableCollection subclasses implementing AddRange with a single multi-item event instead of N single-item events or a Reset; bulk load/unload operations.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- SR.CannotFindRemovedItem
- SR.Format(SR.CollectionAddEventMissingItem, item)
- SR.Generator_Inconsistent
- SR.UnexpectedCollectionChangeAction
- SR.UnexpectedCollectionChangeAction
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/d7ef28e729a2acb5.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/ItemContainerGenerator.cs:2392
if (index < 0)
throw new InvalidOperationException(SR.Format(SR.CollectionAddEventMissingItem, item));
}
}
/// <summary>
/// Forward a CollectionChanged event
/// </summary>
// Called when items collection changes.
private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs args)
{
if (sender != ItemsInternal && args.Action != NotifyCollectionChangedAction.Reset)
return; // ignore events (except Reset) from ItemsCollection when we're listening to group's items.
switch (args.Action)
{
case NotifyCollectionChangedAction.Add:
if (args.NewItems.Count != 1)
throw new NotSupportedException(SR.RangeActionsNotSupported);
OnItemAdded(args.NewItems[0], args.NewStartingIndex);
break;
case NotifyCollectionChangedAction.Remove:
if (args.OldItems.Count != 1)
throw new NotSupportedException(SR.RangeActionsNotSupported);
OnItemRemoved(args.OldItems[0], args.OldStartingIndex);
break;
case NotifyCollectionChangedAction.Replace:
// Don't check arguments if app targets 4.0, for compat ( 726682)
if (!FrameworkCompatibilityPreferences.TargetsDesktop_V4_0)
{
if (args.OldItems.Count != 1)
throw new NotSupportedException(SR.RangeActionsNotSupported);
}
OnItemReplaced(args.OldItems[0], args.NewItems[0], args.NewStartingIndex);
break;View on GitHub (pinned to 81131a70a4)