dotnet/wpf · error · InvalidOperationException
SR.Format(SR.TypeMustImplementIAddChild…
Error message
SR.Format(SR.TypeMustImplementIAddChild, parent.GetType().Name)
What it means
During InstantiateTree, when a factory node holds text content (_text), the framework tries to cast the instantiated parent to IAddChild and call AddText. If the parent type does not implement IAddChild, the text cannot be attached, so an InvalidOperationException naming the parent type is thrown. The factory system relies on IAddChild as the contract for content insertion.
Solutions
- Make the parent type implement IAddChild (AddText at minimum) or use a different parent type that does.
- Instead of SetText on the child factory, use SetValue with an appropriate property (e.g. TextBlock.TextProperty) on a TextBlock factory.
- Remove the SetText call if the parent cannot accept text content.
Example fix
// before
var child = new FrameworkElementFactory(typeof(TextBlock));
child.SetText("hello"); // parent is a custom panel not implementing IAddChild
// after
child.SetValue(TextBlock.TextProperty, "hello"); Defensive patterns
Strategy: type-guard
Validate before calling
if (parentFactory?.Type is Type t && !typeof(IAddChild).IsAssignableFrom(t))
throw new InvalidOperationException($"{t.Name} cannot receive text; implement IAddChild or set a property"); Type guard
bool CanAddText(object o) => o is IAddChild;
Try / catch
try { template.LoadContent(); } catch (InvalidOperationException ex) when (ex.Message.Contains("IAddChild")) { /* use SetValue on a property instead */ } Prevention
- Prefer SetValue(TextBlock.TextProperty, ...) over SetText on arbitrary parents
- Verify parent types implement IAddChild when nesting child factories
- Avoid custom non-IAddChild types as factory parents
When it happens
Trigger: Calling SetText on a FrameworkElementFactory whose parent node instantiates to a type that does not implement IAddChild, then sealing and instantiating the template (e.g. via a ContentPresenter/template expansion).
Common situations: Building a factory tree in code where a text-only child factory is nested under a plain FrameworkElement-derived type (like Grid or StackPanel wrappers that historically implement IAddChild, but custom controls may not); refactoring a control so it no longer implements IAddChild while old factory code still sets text on it.
Understand the failure class
Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.
Related errors
- SR.Format(SR.TypeMustImplementIAddChild…
- SR.Format(SR.CannotHookupFCERoot, type.Name)
- SR.Format(SR.TemplateMustBeFE, new object[] )
- SR.Format(SR.TypeMustImplementIAddChild, _type.Name)
- ' ' is not a Visual or Visual3D.
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/a6fa1e7f7dd26c00.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/FrameworkElementFactory.cs:650
ref FrugalStructList<ChildPropertyDependent> resourceDependents)
{
EventTrace.EasyTraceEvent(EventTrace.Keyword.KeywordXamlBaml, EventTrace.Level.Verbose, EventTrace.Event.WClientParseFefCrInstBegin);
FrameworkElement containerAsFE = container as FrameworkElement;
bool isContainerAnFE = containerAsFE != null;
DependencyObject treeNode = null;
// If we have text, just add it to the parent. Otherwise create the child
// subtree
if (_text != null)
{
// of FrameworkContentElement parent. This is the logical equivalent
// to what happens when adding a child to a visual collection.
IAddChild addChildParent = parent as IAddChild;
if (addChildParent == null)
{
throw new InvalidOperationException(SR.Format(SR.TypeMustImplementIAddChild,
parent.GetType().Name));
}
else
{
addChildParent.AddText(_text);
}
}
else
{
// Factory create instance
treeNode = CreateDependencyObject();
EventTrace.EasyTraceEvent(EventTrace.Keyword.KeywordXamlBaml, EventTrace.Level.Verbose, EventTrace.Event.WClientParseFefCrInstEnd);
// The tree node is either a FrameworkElement or a FrameworkContentElement.
// we'll deal with one or the other...
FrameworkObject treeNodeFO = new FrameworkObject(treeNode);
View on GitHub (pinned to 81131a70a4)