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

  1. Remove the OverridesDefaultStyle setter from the template triggers.
  2. Set OverridesDefaultStyle="True" on the Style that applies the template, or on a named inner element via TargetName.
  3. Control theme-style suppression with BasedOn composition of Styles instead of template triggers.
  4. 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

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


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)