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
- Create a new TriggerAction instance for each trigger/control.
- Remove the action from its current trigger (and detach) before adding it elsewhere.
- Check action.AssociatedObject == null before adding/attaching.
- 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
- One TriggerAction instance per trigger/host.
- Remove actions from old triggers before reusing elsewhere.
- Check AssociatedObject == null before adding.
- Don't reuse action instances across data templates.
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
- ExceptionStringTable.CannotHostBehaviorCollectionMultipleTim…
- ExceptionStringTable.CannotHostTriggerCollectionMultipleTime…
- ExceptionStringTable.CannotHostBehaviorMultipleTimesExceptio…
- ExceptionStringTable.TypeConstraintViolatedExceptionMessage
- ExceptionStringTable.DuplicateItemInCollectionExceptionMessa…
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)