HandyOrg/HandyControl · error · InvalidOperationException

ExceptionStringTable.CannotHostTriggerActionMultipleTimesExc…

Error message

ExceptionStringTable.CannotHostTriggerActionMultipleTimesExceptionMessage

What it means

A TriggerAction can be hosted by only one trigger/object at a time. TriggerAction.Attach throws InvalidOperationException CannotHostTriggerActionMultipleTimesExceptionMessage when called while AssociatedObject is already set to a different object, enforced when a trigger collection/process adds the action (ItemAdded).

Solutions

  1. Create a new TriggerAction instance for each trigger/control.
  2. Remove the action from its current trigger (and detach) before adding it elsewhere.
  3. Check action.AssociatedObject == null before adding/attaching.
  4. Build actions in code per-usage rather than sharing from a resource.

Example fix

// before
var action = new InvokeCommandAction { CommandName = "DoIt" };
trigger1.Actions.Add(action);
trigger2.Actions.Add(action); // throws
// after
trigger1.Actions.Add(new InvokeCommandAction { CommandName = "DoIt" });
trigger2.Actions.Add(new InvokeCommandAction { CommandName = "DoIt" });
Defensive patterns

Strategy: validation

Validate before calling

if (action.AssociatedObject != null && !ReferenceEquals(action.AssociatedObject, target))
    action = (TriggerAction)Activator.CreateInstance(action.GetType());

Type guard

static bool CanAttachAction(TriggerAction a, DependencyObject target) =>
    a.AssociatedObject == null && target != null && a.AssociatedObjectTypeConstraint.IsInstanceOfType(target);

Try / catch

try { trigger.Actions.Add(action); }
catch (InvalidOperationException ex) when (ex.Message.Contains("CannotHostTriggerActionMultipleTimes")) {
    // create a new action instance for this trigger
}

Prevention

When it happens

Trigger: Calling action.Attach(newObject) or adding the same TriggerAction instance (directly or into an EventTrigger.Actions collection) when its AssociatedObject is already non-null and different.

Common situations: Reusing one InvokeCommandAction/CallMethodAction across multiple triggers or controls; adding the same action instance to two EventTriggers; re-attaching an action after reparenting its host without detaching.

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 HandyOrg/HandyControl@2c0875ebd6 (2026-09-14). Data as JSON: /api/errors/bdd6d0090ebf3cf6. Report an issue: GitHub.

Appendix: source

Thrown at src/Shared/System.Windows.Interactivity/TriggerAction.cs:71

        get
        {
            ReadPreamble();
            return _isHosted;
        }
        set
        {
            WritePreamble();
            _isHosted = value;
            WritePostscript();
        }
    }

    public void Attach(DependencyObject dependencyObject)
    {
        if (!Equals(dependencyObject, AssociatedObject))
        {
            if (AssociatedObject != null)
                throw new InvalidOperationException(ExceptionStringTable
                    .CannotHostTriggerActionMultipleTimesExceptionMessage);
            if (dependencyObject != null &&
                !AssociatedObjectTypeConstraint.IsInstanceOfType(dependencyObject))
                throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture,
                    ExceptionStringTable.TypeConstraintViolatedExceptionMessage,
                    new object[]
                        {GetType().Name, dependencyObject.GetType().Name, AssociatedObjectTypeConstraint.Name}));
            WritePreamble();
            _associatedObject = dependencyObject;
            WritePostscript();
            OnAttached();
        }
    }

    public void Detach()
    {
        OnDetaching();
        WritePreamble();

View on GitHub (pinned to 2c0875ebd6)