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

  1. Make the parent type implement IAddChild (AddText at minimum) or use a different parent type that does.
  2. Instead of SetText on the child factory, use SetValue with an appropriate property (e.g. TextBlock.TextProperty) on a TextBlock factory.
  3. 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

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


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)