dotnet/wpf · error · InvalidOperationException

SR.Format(SR.MemberNotAllowedDuringTransaction…

Error message

SR.Format(SR.MemberNotAllowedDuringTransaction, "CancelEdit", "AddNew")

What it means

CancelEdit() discards an EditItem transaction, but throws InvalidOperationException if an AddNew transaction is active. The add and edit transactions are mutually exclusive; cancel the AddNew with CancelNew first.

Solutions

  1. Call CancelNew() when IsAddingNew is true; only call CancelEdit() when IsEditingItem is true.
  2. Order guards: check IsAddingNew before IsEditingItem since AddNew implicitly closes an edit first.
  3. Write a single ResetTransactions(view) helper that checks both flags and calls the matching cancel.
  4. Let the bound control (DataGrid) handle cancel so the correct transaction is targeted.

Example fix

// before
view.CancelEdit(); // cleanup

// after
if (view.IsAddingNew) view.CancelNew();
else if (view.IsEditingItem) view.CancelEdit();
Defensive patterns

Strategy: validation

Validate before calling

// C#
if (view.IsAddingNew) view.CancelNew();
else if (view.IsEditingItem) view.CancelEdit();

Type guard

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

Try / catch

try { view.CancelEdit(); }
catch (InvalidOperationException ex) { Log.Warn("CancelEdit blocked by open AddNew", ex); view.CancelNew(); }

Prevention

When it happens

Trigger: Calling AddNew() then CancelEdit() (instead of CancelNew); a global reset/cleanup routine that unconditionally calls CancelEdit while a new item is pending.

Common situations: Dialog cancel buttons wired to CancelEdit regardless of state; error-handling paths that roll back edits without checking for pending adds; Escape handling in grids where the user was adding a new row.

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

Appendix: source

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

            // editing may change the item's group names (and we can't tell whether
            // it really did).  The best we can do is remove the item and re-insert
            // it.
            if (_isGrouping)
            {
                RemoveItemFromGroups(editItem);
                AddItemToGroups(editItem);
                return;
            }
        }

        /// <summary>
        /// Complete the transaction started by <seealso cref="EditItem"/>.
        /// The pending changes (if any) to the item are discarded.
        /// </summary>
        public void CancelEdit()
        {
            if (IsAddingNew)
                throw new InvalidOperationException(SR.Format(SR.MemberNotAllowedDuringTransaction, "CancelEdit", "AddNew"));
            VerifyRefreshNotDeferred();

            if (_editItem == null)
                return;

            IEditableObject ieo = _editItem as IEditableObject;
            SetEditItem(null);

            if (ieo != null)
            {
                ieo.CancelEdit();
            }
            else
                throw new InvalidOperationException(SR.CancelEditNotSupported);
        }

        private void ImplicitlyCancelEdit()
        {

View on GitHub (pinned to 81131a70a4)