dotnet/wpf · error · InvalidOperationException

SR.Format(SR.MemberNotAllowedDuringAddOrEdit, "Remove")

Error message

SR.Format(SR.MemberNotAllowedDuringAddOrEdit, "Remove")

What it means

Remove(object) deletes the given item from the underlying collection via the view, but throws InvalidOperationException if an AddNew or EditItem transaction is open. Same restriction as RemoveAt: the view will not mutate the collection while tracking a pending new/edited item.

Solutions

  1. Close the open transaction (CommitEdit/CancelEdit, CommitNew/CancelNew) before calling Remove.
  2. Check IsEditingItem and IsAddingNew (or CanRemove) before removing.
  3. In DataGrid scenarios, call CommitEdit on the grid first so the view-level transaction is closed.
  4. Batch operations: cancel/commit once before the loop rather than interleaving Remove with open transactions.

Example fix

// before
foreach (var item in itemsToRemove) view.Remove(item);

// after
if (view.IsEditingItem) view.CancelEdit();
if (view.IsAddingNew) view.CancelNew();
foreach (var item in itemsToRemove) view.Remove(item);
Defensive patterns

Strategy: validation

Validate before calling

// C#
if (!view.IsEditingItem && !view.IsAddingNew && view.CanRemove)
    view.Remove(item);

Type guard

bool CanRemove(IEditableCollectionView v) => !v.IsEditingItem && !v.IsAddingNew;

Try / catch

try { view.Remove(item); }
catch (InvalidOperationException ex) { Log.Warn("Remove during add/edit", ex); }

Prevention

When it happens

Trigger: Calling Remove(item) when IsAddingNew or IsEditingItem is true, e.g. removing the item currently in edit mode.

Common situations: Context-menu 'Delete' invoked on a row that is actively being edited; batch-removal loops that don't close transactions between operations; automated tests that add items via AddNew and then call Remove.

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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Data/BindingListCollectionView.cs:884

        /// The index is interpreted with respect to the view (not with respect to
        /// the underlying collection).
        /// </summary>
        public void RemoveAt(int index)
        {
            if (IsEditingItem || IsAddingNew)
                throw new InvalidOperationException(SR.Format(SR.MemberNotAllowedDuringAddOrEdit, "RemoveAt"));
            VerifyRefreshNotDeferred();

            RemoveImpl(GetItemAt(index), index);
        }

        /// <summary>
        /// Remove the given item from the underlying collection.
        /// </summary>
        public void Remove(object item)
        {
            if (IsEditingItem || IsAddingNew)
                throw new InvalidOperationException(SR.Format(SR.MemberNotAllowedDuringAddOrEdit, "Remove"));
            VerifyRefreshNotDeferred();

            int index = InternalIndexOf(item);
            if (index >= 0)
            {
                RemoveImpl(item, index);
            }
        }

        private void RemoveImpl(object item, int index)
        {
            if (item == CollectionView.NewItemPlaceholder)
                throw new InvalidOperationException(SR.RemovingPlaceholder);

            BindingOperations.AccessCollection(InternalList,
                () =>
                {
                    ProcessPendingChanges();

View on GitHub (pinned to 81131a70a4)