dotnet/wpf · error · ArgumentException

SR.CanOnlyHaveOneChild

Error message

SR.CanOnlyHaveOneChild

What it means

Decorator supports at most one child. Its IAddChild.AddChild throws ArgumentException (CanOnlyHaveOneChild) when a second child is added while Child is already set. This enforces the single-child contract of Decorator-derived elements like Border and Viewbox.

Solutions

  1. Remove the extra child or move all children into a single panel (Grid/StackPanel) inside the Decorator
  2. Use a Panel-derived container (Grid, StackPanel, Canvas) instead of Decorator when multiple children are needed
  3. Set Child once and reuse/update the same UIElement rather than adding again

Example fix

// before
<Border>
  <TextBlock Text="One"/>
  <TextBlock Text="Two"/>
</Border>
// after
<Border>
  <StackPanel>
    <TextBlock Text="One"/>
    <TextBlock Text="Two"/>
  </StackPanel>
</Border>
Defensive patterns

Strategy: validation

Validate before calling

if (decorator.Child != null) throw new InvalidOperationException("Decorator already has a child");

Try / catch

try { ((IAddChild)decorator).AddChild(newChild); }
catch (ArgumentException ex) { /* Child already set */ }

Prevention

When it happens

Trigger: Calling IAddChild.AddChild twice on the same Decorator; XAML markup that places two sibling elements inside a Border/Viewbox/Decorator-derived element.

Common situations: XAML with multiple children inside a Border (e.g. an Image and a TextBlock); refactoring a Grid into a Border and forgetting to nest children in a single panel.

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/bc95142c40047b6b. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/Decorator.cs:70

        ///<summary>
        /// This method is called to Add the object as a child of the Decorator.  This method is used primarily
        /// by the parser; a more direct way of adding a child to a Decorator is to use the <see cref="Child" />
        /// property.
        ///</summary>
        ///<param name="value">
        /// The object to add as a child; it must be a UIElement.
        ///</param>
        void IAddChild.AddChild (Object value)
        {
            if (!(value is UIElement))
            {
                throw new ArgumentException (SR.Format(SR.UnexpectedParameterType, value.GetType(), typeof(UIElement)), nameof(value));
            }

            if (this.Child != null)
            {
                throw new ArgumentException(SR.Format(SR.CanOnlyHaveOneChild, this.GetType(), value.GetType()));
            }

            this.Child = (UIElement)value;
        }

        ///<summary>
        /// This method is called by the parser when text appears under the tag in markup.
        /// As Decorators do not support text, calling this method has no effect if the text
        /// is all whitespace.  For non-whitespace text, throw an exception.
        ///</summary>
        ///<param name="text">
        /// Text to add as a child.
        ///</param> 
        void IAddChild.AddText (string text)
        {
            XamlSerializerUtil.ThrowIfNonWhiteSpaceInAddText(text, this);
        }
        #endregion

View on GitHub (pinned to 81131a70a4)