dotnet/wpf · error · InvalidOperationException
SR.Format(SR.CannotHavePropertyInTemplate…
Error message
SR.Format(SR.CannotHavePropertyInTemplate, FrameworkElement.NameProperty.Name)
What it means
Thrown by ControlTemplate.SealTemplate when the template's visual triggers set the Name property on the templated container. An element's Name participates in the namescope that the template itself defines, so the template cannot assign it to its own container; WPF throws InvalidOperationException at seal time with the property name in the message.
Solutions
- Remove the Name setter from the template triggers.
- Use x:Name on the template's named parts and reference them via TemplateBinding/FindName instead.
- Pass identity through attached properties or Tag rather than Name.
- If building templates in code, skip Setter entries for Name, Style, DefaultStyleKey, and OverridesDefaultStyle on the container.
Example fix
// before (code-built trigger)
var trigger = new Trigger { Property = UIElement.IsEnabledProperty, Value = false };
trigger.Setters.Add(new Setter(FrameworkElement.NameProperty, "root"));
// after
var trigger = new Trigger { Property = UIElement.IsEnabledProperty, Value = false };
trigger.Setters.Add(new Setter(Control.BackgroundProperty, Brushes.Gray));
// name the part in XAML instead: <Border x:Name="root" .../> Defensive patterns
Strategy: validation
Validate before calling
bool templateSetsName(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.NameProperty); Try / catch
try { element.ApplyTemplate(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("Name"))
{
// remove the Name setter; use x:Name on template parts instead
} Prevention
- Name template parts with x:Name in the visual tree, never via trigger setters
- Use TemplatePart attributes and FindName for part access
- Whitelist setter properties when generating templates programmatically
- Exclude Name, Style, DefaultStyleKey, OverridesDefaultStyle from any trigger-setter codegen
When it happens
Trigger: A Setter with Property="Name" (or x:Name-based setter) inside ControlTemplate.Triggers targeting the container. Detected by StyleHelper.IsSetOnContainer during SealTemplate.
Common situations: Generated XAML that serializes element names into trigger setters; copy-paste of property setters including Name from one template to another; code-built templates (FrameworkElementFactory / Trigger setters built programmatically) that add a Name setter.
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.Format(SR.NameNotFound, propertyValue.ChildName)
- SR.Format(SR.NameScopeDuplicateNamesNotAllowed, childName)
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/70e184229b900e32.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/StyleHelper.cs:459
// 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.
// This is used in value computation.
// 2. Optionally adds a ChildPropertyDependent entry to the given
// ContainerRecordFromProperty list. This is used to invalidate
// container dependents.
// 3. Optionally adds a ChildPropertyDependent entry to the given
// ResourceDependents list. This is used when invalidating resource
// referencesView on GitHub (pinned to 81131a70a4)