dotnet/wpf · error · InvalidOperationException

SR.Format(SR.CannotChangeAfterSealed, "TriggerAction")

Error message

SR.Format(SR.CannotChangeAfterSealed, "TriggerAction")

What it means

TriggerAction.CheckSealed() throws InvalidOperationException (CannotChangeAfterSealed, 'TriggerAction') when any mutation is attempted on a TriggerAction after it has been sealed. Sealed objects are frozen into an immutable state once the owning Style/Template is applied, so later edits are rejected.

Solutions

  1. Clone the action (or define a new Style) before modifying, then re-apply the style
  2. Create styles in XAML or before first use; avoid runtime mutation
  3. Check the action's IsSealed property before mutating

Example fix

// before
style.Triggers[0].Actions[0].Parameter = newValue; // throws if sealed
// after
var newStyle = new Style { BasedOn = style };
newAction = new TriggerAction { Parameter = newValue };
newStyle.Triggers[0].Actions.Add(newAction);
control.Style = newStyle;
Defensive patterns

Strategy: validation

Validate before calling

if (action.IsSealed) throw new InvalidOperationException("Action sealed; rebuild style before mutating.");
action.Parameter = newValue;

Type guard

static bool IsMutable(TriggerAction a) => a != null && !a.IsSealed;

Try / catch

try { action.Parameter = v; }
catch (InvalidOperationException ex) when (ex.Message.Contains("TriggerAction")) { /* rebuild style */ }

Prevention

When it happens

Trigger: Mutating properties of a TriggerAction (or its contents) after the containing Style/Template was applied to an element and thus sealed.

Common situations: Modifying a shared style's triggers at runtime after controls using it are rendered; changing EventSetter/InvokeCommandAction parameters from event handlers or timers.

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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/TriggerAction.cs:114

        /// validation checks to see if all parameters make sense.
        /// </summary>
        internal override void Seal()
        {
            if( IsSealed )
            {
                throw new InvalidOperationException(SR.TriggerActionAlreadySealed);
            }
            base.Seal();
        }

        /// <summary>
        ///     Checks sealed status and throws exception if object is sealed
        /// </summary>
        internal void CheckSealed()
        {
            if( IsSealed )
            {
                throw new InvalidOperationException(SR.Format(SR.CannotChangeAfterSealed, "TriggerAction"));
            }
        }

        // Define the DO's inheritance context

        internal override DependencyObject InheritanceContext
        {
            get { return _inheritanceContext; }
        }

        // Receive a new inheritance context (this will be a FE/FCE)
        internal override void AddInheritanceContext(DependencyObject context, DependencyProperty property)
        {
            InheritanceContextHelper.AddInheritanceContext(context,
                                                              this,
                                                              ref _hasMultipleInheritanceContexts,
                                                              ref _inheritanceContext);
        }

View on GitHub (pinned to 81131a70a4)