{"record":{"id":"464b13c95cf15657","repo":"dotnet/wpf","slug":"throw-new-invalidoperationexception-sr","errorCode":null,"errorMessage":"throw new InvalidOperationException(SR.CompositeCollectionResetOnlyOnClear);","messagePattern":"throw new InvalidOperationException\\(SR\\.CompositeCollectionResetOnlyOnClear\\);","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/Data/CompositeCollectionView.cs","lineNumber":624,"sourceCode":"                    break;\n\n\n                case NotifyCollectionChangedAction.Reset:\n                    {\n                        _traceLog?.Add(\"ProcessCollectionChanged  action = {0}\", args.Action);\n\n                        if (_collection.Count != 0)\n                        {\n                            //\n                            //  This is to verify that a Reset event is raised IFF the CompositionCollection\n                            //  was cleared.  To fully implement a Reset event otherwise can prove to be\n                            //  quite complex.  For example, you must unhook the listeners to each of the\n                            //  CollectionContainers that are no longer in the collection, hook up the new\n                            //  ones, and figure out how to restore the currency to the correct item in\n                            //  the correct sub-collection, or to BeforeFirst or AfterLast.\n                            //\n\n                            throw new InvalidOperationException(SR.CompositeCollectionResetOnlyOnClear);\n                        }\n\n                        _count = 0; // OnCollectionChanged(arg) below will raise PropChange for Count\n                        if (_currentPositionX >= 0) // if current item was in view\n                        {\n                            OnCurrentChanging();\n                            SetCurrentBeforeFirst();\n                            OnCurrentChanged();\n\n                            OnPropertyChanged(IsCurrentBeforeFirstPropertyName);\n                            OnPropertyChanged(CurrentPositionPropertyName);\n                            OnPropertyChanged(CurrentItemPropertyName);\n                        }\n                    }\n                    break;\n\n                default:\n                    throw new NotSupportedException(SR.Format(SR.UnexpectedCollectionChangeAction, args.Action));","sourceCodeStart":606,"sourceCodeEnd":642,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/Data/CompositeCollectionView.cs#L606-L642","documentation":"CompositeCollectionView supports a Reset (collection changed) notification only when the composite collection was cleared. Any other Reset (the source CompositeCollection changed structurally in a way other than clearing) cannot be reconciled with currency and live grouping bookkeeping, so ProcessCollectionChanged throws InvalidOperationException.","triggerScenarios":"Raising/forwarding a CollectionChanged Reset event on a CompositeCollection whose items were not simply emptied - e.g. replacing the whole CompositeCollection contents with new CollectionContainers and firing Reset instead of Add/Remove, or re-initializing the CompositeCollection in place.","commonSituations":"Rebuilding a CompositeCollection at runtime by mutating it and firing Reset; third-party sources that coalesce all changes into a Reset; code that mimics ObservableCollection.Clear with Reset after substituting containers.","solutions":["Fire Reset only when the CompositeCollection was actually emptied; otherwise raise granular Add/Remove/Replace/Move notifications.","Replace the whole CompositeCollection instance (assign a new object) instead of mutating it and signaling Reset.","Wrap the update so each contained collection's own changes propagate individually rather than being collapsed into a parent Reset."],"exampleFix":"// before\ncompositeCollection.Clear();\ncompositeCollection.Add(newContainer);\nonCollectionChanged(NotifyCollectionChangedAction.Reset);\n\n// after\ncompositeCollection.Clear(); // Reset is legal here\ncompositeCollection.Add(newContainer); // raise Add for this change instead of Reset","handlingStrategy":"validation","validationCode":"if (action == NotifyCollectionChangedAction.Reset && compositeCollection.Count > 0)\n    throw new InvalidOperationException(\"Reset is only supported when the CompositeCollection is cleared\");","typeGuard":null,"tryCatchPattern":"try { ApplyChange(e); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"Reset\"))\n{ RefreshViewFromScratch(); }","preventionTips":["Only fire Reset after an actual Clear of the CompositeCollection.","Replace whole CompositeCollection instances rather than mutating and signaling Reset.","Keep granular Add/Remove notifications for any non-clear structural change."],"tags":["wpf","collection-view","reset","collection-changed"],"backgroundTag":"unsupported-operation","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-21T21:30:21.729Z"}