{"record":{"id":"237326d8b31314b3","repo":"stride3d/stride","slug":"can-only-change-selecteditems-collection-in-multiple","errorCode":null,"errorMessage":"Can only change SelectedItems collection in multiple selection modes. Use SelectedItem in single select modes.","messagePattern":"Can only change SelectedItems collection in multiple selection modes\\. Use SelectedItem in single select modes\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/presentation/Stride.Core.Presentation.Wpf/Controls/TreeView.cs","lineNumber":632,"sourceCode":"                        if (item != null)\n                            item.IsSelected = false;\n                        treeView.SelectedItems.RemoveAt(i);\n                    }\n                    treeView.updatingSelection = false;\n                    break;\n\n                default:\n                    throw new ArgumentOutOfRangeException();\n            }\n        }\n\n        private void OnSelectedItemsChanged(object sender, NotifyCollectionChangedEventArgs e)\n        {\n            if (updatingSelection)\n                return;\n\n            if (SelectionMode == SelectionMode.Single && !allowedSelectionChanges)\n                throw new InvalidOperationException(\"Can only change SelectedItems collection in multiple selection modes. Use SelectedItem in single select modes.\");\n\n            updatingSelection = true;\n\n            switch (e.Action)\n            {\n                case NotifyCollectionChangedAction.Add:\n                    object last = null;\n                    foreach (var item in GetTreeViewItemsFor(e.NewItems))\n                    {\n                        item.IsSelected = true;\n\n                        last = item.DataContext;\n                    }\n\n                    SelectedItem = last;\n                    break;\n                case NotifyCollectionChangedAction.Remove:\n                    foreach (var item in GetTreeViewItemsFor(e.OldItems))","sourceCodeStart":614,"sourceCodeEnd":650,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/presentation/Stride.Core.Presentation.Wpf/Controls/TreeView.cs#L614-L650","documentation":"The TreeView exposes SelectedItems as an observable collection, but direct mutation is only meaningful in multi-selection modes. In Single selection mode the control keeps SelectedItems in sync with SelectedItem itself; an external add/remove that was not initiated by the control (allowedSelectionChanges false) raises this InvalidOperationException to protect the single-selection invariant.","triggerScenarios":"Calling treeView.SelectedItems.Add(item) / Remove / Clear while SelectionMode is Single, outside of control-internal updates (updatingSelection false and allowedSelectionChanges false).","commonSituations":"Code shared between single- and multi-select trees that mutates SelectedItems; restoring saved selection state on a Single-mode tree; data-binding code writing into the collection.","solutions":["Set treeView.SelectedItem = item instead of modifying SelectedItems when in Single mode.","Switch the TreeView to SelectionMode.Extended if collection mutation is required.","Guard mutation logic on the current SelectionMode before touching SelectedItems."],"exampleFix":"// before\ntreeView.SelectedItems.Clear();\ntreeView.SelectedItems.Add(node);\n// after\nif (treeView.SelectionMode == SelectionMode.Single)\n    treeView.SelectedItem = node;\nelse {\n    treeView.SelectedItems.Clear();\n    treeView.SelectedItems.Add(node);\n}","handlingStrategy":"validation","validationCode":"if (treeView.SelectionMode == SelectionMode.Single)\n    treeView.SelectedItem = node; // not SelectedItems\nelse { treeView.SelectedItems.Clear(); treeView.SelectedItems.Add(node); }","typeGuard":"bool CanMutateSelectedItems(TreeView tv) => tv.SelectionMode != SelectionMode.Single;","tryCatchPattern":"try { treeView.SelectedItems.Add(node); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"multiple selection modes\")) { treeView.SelectedItem = node; }","preventionTips":["Always use SelectedItem in Single mode; treat SelectedItems as read-only there.","Extract a SetSelection(treeView, node) helper that branches on mode.","When restoring saved state, apply the same mode-aware selection helper."],"tags":["wpf","treeview","selection-mode","invalid-state"],"backgroundTag":"invalid-state-transition","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}