dotnet/wpf · error · InvalidOperationException

SR.ListView_GridViewColumnCollectionIsReadOnly

Error message

SR.ListView_GridViewColumnCollectionIsReadOnly

What it means

Thrown by GridViewColumnCollection.VerifyAccess when the collection is immutable (IsImmutable) and a mutating operation (Clear/Remove/Insert/Set/Move) is attempted. A GridViewColumnCollection becomes immutable once it is in use by an attached GridView, typically during layout or when the view has been applied. It guards read-only collection state against structurally invalid mutations.

Solutions

  1. Perform modifications on the UI thread and outside of layout (e.g. via Dispatcher.BeginInvoke at Background priority or later)
  2. Check collection ownership state before mutating; defer changes until after the view is applied
  3. Reentrancy: complete the in-progress column change before issuing another mutation

Example fix

// before
void OnLoaded(object s, RoutedEventArgs e) => gridView.Columns.Add(newColumn); // may run during layout
// after
void OnLoaded(object s, RoutedEventArgs e) => Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() => gridView.Columns.Add(newColumn)));
Defensive patterns

Strategy: validation

Validate before calling

// queue mutation off-layout
Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() => gridView.Columns.Add(col)));

Type guard

null

Try / catch

try { gridView.Columns.Add(col); } catch (InvalidOperationException ex) { Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() => gridView.Columns.Add(col))); }

Prevention

When it happens

Trigger: Calling Add/Insert/Remove/Clear/Move/SetItem on a GridViewColumnCollection whose IsImmutable is true — commonly a collection that already belongs to an attached GridView or is accessed during a layout/property-changed pass.

Common situations: Modifying GridView.Columns from a background thread or inside a rendering/layout callback; attempting to edit a collection after the GridView has been applied to a ListView in certain deferred states; reentrancy during a column change notification.

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


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/GridViewColumnCollection.cs:439

            ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(index, _actualIndices.Count, indexName);
        }

        // Throw if column is null or already existed in a GVCC
        private void ValidateColumnForInsert(GridViewColumn column)
        {
            ArgumentNullException.ThrowIfNull(column);

            if (column.ActualIndex >= 0)
            {
                throw new InvalidOperationException(SR.ListView_NotAllowShareColumnToTwoColumnCollection);
            }
        }

        private void VerifyAccess()
        {
            if (IsImmutable)
            {
                throw new InvalidOperationException(SR.ListView_GridViewColumnCollectionIsReadOnly);
            }

            // Although CheckReentrancy() is called in base class, we still need to call it here again,
            // otherwise, when Reentrancy is found and exception is thrown, our operation is done and can't be undo.
            CheckReentrancy();
        }

        #endregion

        //------------------------------------------------------
        //
        //  Private Fields
        //
        //------------------------------------------------------

        #region Private Fields

        // internal storage of CollumnCollection

View on GitHub (pinned to 81131a70a4)