dotnet/wpf · error · InvalidOperationException
SR.Format(SR.CannotChangeAfterSealed, "EventTrigger")
Error message
SR.Format(SR.CannotChangeAfterSealed, "EventTrigger")
What it means
EventTrigger.RoutedEvent's setter throws InvalidOperationException (CannotChangeAfterSealed) if the trigger has been sealed. Sealing happens when the trigger becomes part of a Style/ControlTemplate in use, after which its configuration is immutable for thread-safety.
Solutions
- Set RoutedEvent before adding the trigger to the style/template
- Create a new EventTrigger with the desired RoutedEvent and replace it in the collection (before the style is applied)
- Recreate the entire Style/Template rather than mutating sealed triggers
Example fix
// before
var trig = new EventTrigger();
style.Triggers.Add(trig);
ApplyStyle();
trig.RoutedEvent = Button.ClickEvent; // throws
// after
var trig = new EventTrigger { RoutedEvent = Button.ClickEvent };
style.Triggers.Add(trig); Defensive patterns
Strategy: validation
Validate before calling
if (trigger.IsSealed) throw new InvalidOperationException("Create a new EventTrigger instead of mutating a sealed one"); Type guard
bool CanConfigure(EventTrigger t) => !t.IsSealed;
Try / catch
try { trigger.RoutedEvent = ev; }
catch (InvalidOperationException ex) when (ex.Message.Contains("sealed")) { trigger = new EventTrigger { RoutedEvent = ev }; } Prevention
- Configure triggers fully before adding to styles/templates
- Treat sealed style resources as immutable at runtime
When it happens
Trigger: Setting trigger.RoutedEvent after the EventTrigger was added to a Style.Triggers / FrameworkTemplate.Triggers collection that has been sealed.
Common situations: Mutating shared style triggers at runtime; trying to retarget an EventTrigger after the style was applied to controls; editing template triggers post-layout.
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
- SR.Format(SR.CannotChangeAfterSealed, "SetterBase")
- SR.EventTriggerDoesNotEnterExit
- SR.EventTriggerDoNotSetProperties
- SR.Format(SR.CannotChangeAfterSealed…
- SR.Format(SR.CannotChangeAfterSealed, "Style")
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/4d74d9bdefe090d5.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/EventTrigger.cs:96
}
/// <summary>
/// The Event that will activate this trigger - one must be specified
/// before an event trigger is meaningful.
/// </summary>
public RoutedEvent RoutedEvent
{
get
{
return _routedEvent;
}
set
{
ArgumentNullException.ThrowIfNull(value);
if ( IsSealed )
{
throw new InvalidOperationException(SR.Format(SR.CannotChangeAfterSealed, "EventTrigger"));
}
// When used as an element trigger, we don't actually need to seal
// to ensure cross-thread usability. However, if we *are* fixed on
// listening to an event already, don't allow this change.
if( _routedEventHandler != null )
{
// Recycle the Seal error message.
throw new InvalidOperationException(SR.Format(SR.CannotChangeAfterSealed, "EventTrigger"));
}
_routedEvent = value;
}
}
/// <summary>
/// The x:Name of the object whose event shall trigger this
/// EventTrigger. If null, then this is the object being StyledView on GitHub (pinned to 81131a70a4)