dotnet/wpf · error · InvalidOperationException
SR.Format(SR.CannotHavePropertyInTemplate…
Error message
SR.Format(SR.CannotHavePropertyInTemplate, FrameworkElement.OverridesDefaultStyleProperty.Name)
What it means
Thrown by ControlTemplate.SealTemplate when the template's visual triggers set OverridesDefaultStyle on the templated container. OverridesDefaultStyle controls whether theme styles apply to the container; letting a template toggle it on its own container is disallowed, and WPF throws InvalidOperationException during sealing. The message names the property (OverridesDefaultStyle).
Solutions
- Remove the OverridesDefaultStyle setter from the template triggers.
- Set OverridesDefaultStyle="True" on the Style that applies the template, or on a named inner element via TargetName.
- Control theme-style suppression with BasedOn composition of Styles instead of template triggers.
- Pre-validate template XAML for the forbidden container properties Style/DefaultStyleKey/OverridesDefaultStyle/Name.
Example fix
<!-- before -->
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="OverridesDefaultStyle" Value="True"/>
</Trigger>
</ControlTemplate.Triggers>
<!-- after -->
<Style TargetType="Button" BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="Template" Value="{StaticResource MyTemplate}"/>
</Style> Defensive patterns
Strategy: validation
Validate before calling
bool templateSetsOverridesDefaultStyle(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.OverridesDefaultStyleProperty); Try / catch
try { element.Template = t; }
catch (InvalidOperationException ex) when (ex.Message.Contains("OverridesDefaultStyle"))
{
// move the setting to the Style level and retry
} Prevention
- Set OverridesDefaultStyle at Style level or on named inner elements, not in template triggers
- Use BasedOn to compose theme styles instead of toggling OverridesDefaultStyle
- Lint templates for the four forbidden container properties
- When copying trigger XAML between Style and Template scopes, strip container-property setters
When it happens
Trigger: A Setter with Property="OverridesDefaultStyle" inside ControlTemplate.Triggers (or any template visual trigger affecting the container). Raised by StyleHelper.IsSetOnContainer when the template is sealed.
Common situations: XAML copied from a Style-level trigger (where OverridesDefaultStyle setters are legal on inner elements) pasted into template triggers; attempts to suppress theme styling for one trigger state; migration of WPF 3.x-era markup into stricter template parsing paths.
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.CannotHavePropertyInTemplate…
- SR.Format(SR.CannotHavePropertyInTemplate…
- SR.Format(SR.CannotHavePropertyInTemplate…
- SR.TemplateTargetTypeMismatch
- SR.TriggersSupportsEventTriggersOnly
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/c31e11acda4ce849.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/StyleHelper.cs:452
// 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.
if (StyleHelper.IsSetOnContainer(FrameworkElement.NameProperty, ref containerDependents, true))
{
throw new InvalidOperationException(SR.Format(SR.CannotHavePropertyInTemplate, FrameworkElement.NameProperty.Name));
}
}
//
// All table datastructures read-lock-free/write-lock
// UpdateTables writes the datastructures, locks set by callers
//
// This method
// 1. Adds a ChildValueLookup entry to the given ChildRecord.View on GitHub (pinned to 81131a70a4)