dotnet/wpf · error · InvalidOperationException

SR.DeferSelectionActive

Error message

SR.DeferSelectionActive

What it means

BeginUpdateSelectedItems starts a deferred selection scope in which SelectedItems.Add/Remove are queued until EndUpdateSelectedItems. It throws InvalidOperationException if a selection change is already active (_selector.SelectionChange.IsActive) or a deferred update is already in progress (_updatingSelectedItems), preventing nested/overlapping selection transactions.

Solutions

  1. Ensure Begin/End pairs are balanced and never nested; add a bool guard around reentrant calls.
  2. Don't start a deferred update from inside SelectionChanged; defer with Dispatcher.BeginInvoke.
  3. Consolidate selection logic into a single UpdateSelectedItems scope.
  4. Track scope ownership (e.g. ref-count or flag) in helper code shared by multiple event handlers.

Example fix

// before
void OnSelectionChanged(...) { listBox.UpdateSelectedItems(() => { ... }); }
// after
void OnSelectionChanged(...) { Dispatcher.BeginInvoke(new Action(() => listBox.UpdateSelectedItems(() => { ... }))); }
Defensive patterns

Strategy: validation

Validate before calling

if (!isUpdatingSelectedItems && !selectionChangeActive) StartDeferredSelection();

Type guard

bool canBeginUpdate = !listBox.IsSelectionChangeActive;

Try / catch

try { BeginUpdateSelectedItems(); ... }
catch (InvalidOperationException) { /* already active: join or defer the existing scope */ }

Prevention

When it happens

Trigger: Calling BeginUpdateSelectedItems (or Selector.UpdateSelectedItems) while another SelectionChange is active — e.g. calling it from within a SelectionChanged handler, from OnSelectedCellsChanged, or nesting one UpdateSelectedItems call inside another.

Common situations: Reentrancy: modifying selection inside SelectionChanged which itself runs during a selection change; a helper method calling UpdateSelectedItems while the caller already holds the deferred scope.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14). Data as JSON: /api/errors/59843756fcda914e. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/SelectedItemCollection.cs:188

            private SelectedItemCollection _owner;
        }

        private int _changeCount;
        private Changer _changer;

        #endregion Reentrant changes

        #region MultiSelector methods

        /// <summary>
        /// Begin tracking selection changes. SelectedItems.Add/Remove will queue up the changes but not commit them until EndUpdateSelecteditems is called.
        /// </summary>
        internal void BeginUpdateSelectedItems()
        {
            if (_selector.SelectionChange.IsActive || _updatingSelectedItems)
            {
                throw new InvalidOperationException(SR.DeferSelectionActive);
            }
            _updatingSelectedItems = true;
            _selector.SelectionChange.Begin();
        }

        /// <summary>
        /// Commit selection changes.
        /// </summary>
        internal void EndUpdateSelectedItems()
        {
            if (!_selector.SelectionChange.IsActive || !_updatingSelectedItems)
            {
                throw new InvalidOperationException(SR.DeferSelectionNotActive);
            }
            _updatingSelectedItems = false;
            _selector.SelectionChange.End();
        }

View on GitHub (pinned to 81131a70a4)