dotnet/wpf · error · ArgumentException

SR.MustBeTriggerAction

Error message

SR.MustBeTriggerAction

What it means

TriggerActionCollection.VerifyIsTriggerAction throws ArgumentException with SR.MustBeTriggerAction when an object that is not a TriggerAction is added to or removed from a TriggerActionCollection. If the value is null it throws ArgumentNullException instead; otherwise a non-null, wrong-typed object reaches this guard.

Solutions

  1. Only add instances of TriggerAction subclasses (e.g., InvokeCommandAction, EventTrigger actions) to Actions
  2. Move Setter elements into the trigger's Setters collection, not Actions
  3. Check 'is TriggerAction' before Add/Insert

Example fix

// before
trigger.Actions.Add(new Setter.PropertySetter()); // wrong type
// after
if (item is TriggerAction ta) { trigger.Actions.Add(ta); }
else { trigger.Setters.Add((SetterBase)item); }
Defensive patterns

Strategy: type-guard

Validate before calling

if (item is TriggerAction) { actions.Add(item); } else { throw new ArgumentException(nameof(item)); }

Type guard

static bool IsTriggerAction(object o) => o is TriggerAction;

Try / catch

try { actions.Add(item); }
catch (ArgumentException ex) when (ex.Message.Contains("TriggerAction")) { /* wrong item type */ }

Prevention

When it happens

Trigger: Passing a Setter, Trigger, arbitrary DependencyObject, or other non-TriggerAction object to Actions.Add/Insert/indexer-set/Remove/Contains/IndexOf of a TriggerActionCollection.

Common situations: XAML where a <Setter> is nested inside <Trigger.Actions> instead of <Trigger.Setters>; code-built triggers placing wrong items in the collection.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/TriggerActionCollection.cs:305

        // Throw if a change is attempted at a time we're not allowing them
        private void CheckSealed()
        {
            if ( _sealed )
            {
                throw new InvalidOperationException(SR.Format(SR.CannotChangeAfterSealed, "TriggerActionCollection"));
            }            
        }

        // Throw if the given object isn't a TriggerAction
        private TriggerAction VerifyIsTriggerAction(object value)
        {
            TriggerAction action = value as TriggerAction;

            if ( action == null )
            {
                ArgumentNullException.ThrowIfNull(value);

                throw new ArgumentException(SR.MustBeTriggerAction);
            }

            return action;
        }



        // The actual underlying storage for our TriggerActions
        private List<TriggerAction> _rawList;

        // Whether we are allowing further changes to the collection
        private bool _sealed = false;

        // The event trigger that we're in
        private DependencyObject _owner = null;
        
    }
}

View on GitHub (pinned to 81131a70a4)