dotnet/wpf · error · InvalidOperationException
SR.Format(SR.CannotHavePropertyInTemplate…
Error message
SR.Format(SR.CannotHavePropertyInTemplate, FrameworkElement.StyleProperty.Name)
What it means
Thrown by ControlTemplate.SealTemplate (via StyleHelper) when a template's visual triggers set the Style property on the templated container. A template cannot define the Style of its own container, since Style and Template are mutually determined; WPF forbids it to prevent infinite template resolution. The exception is an InvalidOperationException raised while sealing the template, i.e. when the template is first applied.
Solutions
- Remove the Setter that targets the Style property from the template's Triggers; set Style via the Style itself or on the control instance instead.
- If the intent was to restyle the template root element, give the root a named child (x:Name) and target the Setter with TargetName="...", or set properties directly.
- Replace the Style setter with individual property setters (e.g. Background, Foreground) inside the trigger.
- Verify which template triggers set container-dependent properties before applying the template; StyleHelper.IsSetOnContainer flags Style, DefaultStyleKey, OverridesDefaultStyle, and Name.
Example fix
<!-- before -->
<ControlTemplate TargetType="Button">
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Style" Value="{StaticResource HoverStyle}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<!-- after -->
<ControlTemplate TargetType="Button">
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="LightBlue"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate> Defensive patterns
Strategy: validation
Validate before calling
bool templateSetsContainerStyle(ControlTemplate t) =>
t.Triggers.Cast<TriggerBase>().SelectMany(tr => tr is MultiTrigger mt ? mt.Setters : tr.Setters.Cast<SetterBase>())
.OfType<Setter>().Any(s => s.Property == FrameworkElement.StyleProperty); Try / catch
try { element.Template = template; element.ApplyTemplate(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("Style"))
{
// log template name; strip offending container setters before retrying
} Prevention
- Never put setters for Style, DefaultStyleKey, OverridesDefaultStyle, or Name inside ControlTemplate.Triggers
- Set styles on the Style element or control instance, not the template
- Lint XAML templates for container property setters before build
- When generating templates in code, whitelist the properties setters may target
When it happens
Trigger: Defining a ControlTemplate (or FrameworkTemplate) whose Trigger, MultiTrigger, or TriggerBase setters contain a Setter with Property="Style" targeting the container (TargetName omitted or set to the template root that maps to the container dependent property list). The error surfaces at template seal time — typically when the template is applied to a control.
Common situations: Copy-pasting a style trigger block into a template's <ControlTemplate.Triggers> and accidentally leaving a Setter for Style; tool-generated XAML that merges Style-level and template-level triggers; refactoring a Style so its Style setter drifted into the template triggers.
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
- (no message - parameterless InvalidOperationException)
- SR.AddText_Invalid
- SR.Animation_NoTextChildren
- SR.Animation_NoTextChildren
- SR.Animation_NoTextChildren
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/a0597de547bb0f7a.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/StyleHelper.cs:438
// All done, seal self and call it a day.
isSealed = true;
// Remove thread affinity so it can be accessed across threads
frameworkTemplate.DetachFromDispatcher();
// Check if the template has the Template property set on the container via its visual triggers.
// It is an error to specify the TemplateProperty in your own Template.
if (StyleHelper.IsSetOnContainer(Control.TemplateProperty, ref containerDependents, true) ||
StyleHelper.IsSetOnContainer(ContentPresenter.TemplateProperty, ref containerDependents, true))
{
throw new InvalidOperationException(SR.Format(SR.CannotHavePropertyInTemplate, Control.TemplateProperty.Name));
}
// Check if the template has the Style property set on the container via its visual triggers.
// It is an error to specify the StyleProperty in your own Template.
if (StyleHelper.IsSetOnContainer(FrameworkElement.StyleProperty, ref containerDependents, true))
{
throw new InvalidOperationException(SR.Format(SR.CannotHavePropertyInTemplate, FrameworkElement.StyleProperty.Name));
}
// Check if the template has the DefaultStyleKey property set on the container via its visual triggers.
// It is an error to specify the DefaultStyleKeyProperty in your own Template.
if (StyleHelper.IsSetOnContainer(FrameworkElement.DefaultStyleKeyProperty, ref containerDependents, true))
{
throw new InvalidOperationException(SR.Format(SR.CannotHavePropertyInTemplate, FrameworkElement.DefaultStyleKeyProperty.Name));
}
// Check if the template has the OverridesDefaultStyle property set on the container via its visual triggers.
// It is an error to specify the OverridesDefaultStyleProperty in your own Template.
if (StyleHelper.IsSetOnContainer(FrameworkElement.OverridesDefaultStyleProperty, ref containerDependents, true))
{
throw new InvalidOperationException(SR.Format(SR.CannotHavePropertyInTemplate, FrameworkElement.OverridesDefaultStyleProperty.Name));
}
// Check if the template has the Name property set on the container via its visual triggers.
// It is an error to specify the Name in your own Template.View on GitHub (pinned to 81131a70a4)