dotnet/wpf · error · InvalidOperationException

SR.DeferSelectionNotActive

Error message

SR.DeferSelectionNotActive

What it means

EndUpdateSelectedItems commits the queued selection changes and must only be called while a deferred selection is actually active (SelectionChange.IsActive AND _updatingSelectedItems). Calling it without a matching BeginUpdateSelectedItems — or after the selection change already ended — throws InvalidOperationException (DeferSelectionNotActive).

Solutions

  1. Always pair Begin/End in a try/finally so End runs only after a successful Begin.
  2. Ensure End is called exactly once per Begin.
  3. Catch exceptions inside the update block so the scope is properly committed or rolled back.
  4. Avoid hand-rolling Begin/End; use Selector.UpdateSelectedItems which manages the scope.

Example fix

// before
listBox.BeginUpdateSelectedItems(); DoWork(); listBox.EndUpdateSelectedItems();
// after
listBox.BeginUpdateSelectedItems();
try { DoWork(); }
finally { listBox.EndUpdateSelectedItems(); }
Defensive patterns

Strategy: validation

Validate before calling

if (beganUpdate && !endedUpdate) EndUpdateSelectedItems();

Prevention

When it happens

Trigger: Calling EndUpdateSelectedItems without a prior successful BeginUpdateSelectedItems; calling it twice; calling it from code paths (OnExecutedDelete, OnSelectedCellsChanged, MakeFullRowSelection, UpdateSelectedItems) when the underlying SelectionChange was terminated early (e.g. by an exception between Begin and End).

Common situations: Unbalanced try/finally around Begin/End; an exception inside the update block leaves state inconsistent; custom code mimicking DataGrid internals calls End without Begin.

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/86d6d25fdd98861d. Report an issue: GitHub.

Appendix: source

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

        /// </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();
        }

        /// <summary>
        /// Returns true after BeginUpdateSelectedItems is called
        /// </summary>
        internal bool IsUpdatingSelectedItems
        {
            get
            {
                return _selector.SelectionChange.IsActive || _updatingSelectedItems;
            }
        }

        /// <summary>
        /// Add an ItemInfo to the deferred selection

View on GitHub (pinned to 81131a70a4)