dotnet/wpf · error · InvalidOperationException
SR.Format(SR.UnsupportedTriggerInTemplate…
Error message
SR.Format(SR.UnsupportedTriggerInTemplate, triggerBase.GetType().Name)
What it means
ProcessTemplateTriggers iterates a ControlTemplate's Triggers and throws when the trigger is neither a Trigger, nor a MultiTrigger/DataTrigger usable with actions, i.e. a trigger type unsupported inside templates was supplied (most commonly an EventTrigger in a position the code path treats as a BaseValue trigger, or a custom TriggerBase).
Solutions
- Remove the unsupported trigger from ControlTemplate.Triggers or replace it with a supported Trigger/MultiTrigger
- Move EventTrigger logic out of the template into element.Triggers or style triggers
- For custom trigger behavior, implement a TriggerAction-free approach such as visual states or attached behavior
- Log triggerBase.GetType() in your validation pass to identify the offending type
Example fix
// before
<ControlTemplate.Triggers>
<EventTrigger RoutedEvent="ButtonBase.Click"><BeginStoryboard/></EventTrigger>
</ControlTemplate.Triggers>
// after
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Opacity" Value="0.8"/>
</Trigger>
</ControlTemplate.Triggers> Defensive patterns
Strategy: validation
Validate before calling
foreach (var t in template.Triggers)
if (!(t is Trigger || t is MultiTrigger || t is DataTrigger))
throw new InvalidOperationException(t.GetType().Name + " not supported in template triggers"); Type guard
bool TemplateTriggerSupported(TriggerBase t) => t is Trigger || t is MultiTrigger || t is DataTrigger;
Try / catch
try { fe.Template = template; } catch (InvalidOperationException ex) when (ex.Message.Contains("not supported")) { fe.Triggers.AddRange(template.Triggers); fe.Template = null; } Prevention
- Keep EventTriggers in Style.Triggers or element.Triggers, not ControlTemplate.Triggers
- Only use the four built-in trigger types in templates
- Recheck templates after migrating between .NET versions
When it happens
Trigger: Setting ControlTemplate.Triggers to a trigger type not in {Trigger, MultiTrigger, DataTrigger} — e.g. a hand-added EventTrigger that failed the earlier eventTrigger branch check, or a custom class derived from TriggerBase.
Common situations: Copying Style triggers into a template and leaving an EventTrigger in the collection; third-party libraries adding custom trigger types; refactoring a Style into a template without pruning trigger kinds.
Related errors
- E_NOTIMPL
- new NotSupportedException() // Only support color spaces…
- SR.CannotChangeAfterSealed
- SR.ChildTemplateInstanceDoesNotExist
- SR.ConditionCannotUseBothPropertyAndBinding
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/67601b858e2fc5ac.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/StyleHelper.cs:982
StyleHelper.AddPropertyTriggerWithAction( triggerBase, triggerCondition.Property, ref propertyTriggersWithActions );
}
}
else if( dataTrigger != null )
{
StyleHelper.AddDataTriggerWithAction( triggerBase, dataTrigger.Binding, ref dataTriggersWithActions );
}
else if( multiDataTrigger != null )
{
for( int k = 0; k < multiDataTrigger.Conditions.Count; k++ )
{
Condition dataCondition = multiDataTrigger.Conditions[k];
StyleHelper.AddDataTriggerWithAction( triggerBase, dataCondition.Binding, ref dataTriggersWithActions );
}
}
else
{
throw new InvalidOperationException(SR.Format(SR.UnsupportedTriggerInTemplate, triggerBase.GetType().Name));
}
}
}
else if( eventTrigger != null )
{
StyleHelper.ProcessEventTrigger(eventTrigger,
childIndexFromChildID,
ref triggerActions,
ref eventDependents,
templateRoot,
frameworkTemplate,
ref eventHandlersStore,
ref hasLoadedChangeHandler);
}
else
{
throw new InvalidOperationException(SR.Format(SR.UnsupportedTriggerInTemplate, triggerBase.GetType().Name));
}View on GitHub (pinned to 81131a70a4)