dotnet/wpf · error · ArgumentException

SR.Format(SR.MustBeFrameworkOr3DDerived, value.Name)

Error message

SR.Format(SR.MustBeFrameworkOr3DDerived, value.Name)

What it means

The FrameworkElementFactory.Type setter only accepts types derived from FrameworkElement, FrameworkContentElement, or Visual3D. Assigning any other Type throws this ArgumentException naming the offending type. FrameworkElementFactory can only instantiate WPF framework-level elements for template content.

Solutions

  1. Only assign types deriving from FrameworkElement (e.g. TextBlock, Border), FrameworkContentElement, or Visual3D.
  2. For non-visual data, keep the CLR object as DataContext/Content and use a FrameworkElement-derived presenter inside the template.
  3. Pre-validate the candidate Type before assignment with the same IsAssignableFrom checks WPF uses.

Example fix

// before
factory.Type = typeof(MyDataRecord); // throws

// after
factory.Type = typeof(ContentPresenter); // FrameworkElement-derived, show data via bindings
Defensive patterns

Strategy: validation

Validate before calling

static bool IsSupportedElementType(Type t) =>
    t is not null &&
    (typeof(FrameworkElement).IsAssignableFrom(t) ||
     typeof(FrameworkContentElement).IsAssignableFrom(t) ||
     typeof(Visual3D).IsAssignableFrom(t));

if (!IsSupportedElementType(candidateType))
    throw new ArgumentException($"{candidateType.Name} must derive from FrameworkElement, FrameworkContentElement, or Visual3D.");

Type guard

bool IsValidFactoryType(Type? t) => t is not null && (typeof(FrameworkElement).IsAssignableFrom(t) || typeof(FrameworkContentElement).IsAssignableFrom(t) || typeof(Visual3D).IsAssignableFrom(t));

Try / catch

try { factory.Type = candidateType; }
catch (ArgumentException ex) { logger.LogWarning(ex, "Unsupported factory type {Type}", candidateType.Name); }

Prevention

When it happens

Trigger: Setting factory.Type to typeof(string), a POCO, a struct, a non-Visual custom class, or any type outside the three supported hierarchies.

Common situations: Trying to host arbitrary CLR objects directly in a template instead of binding data; generating templates via reflection where the fetched Type is a model type, not a control; targeting types from assemblies not referencing PresentationFramework.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14). Data as JSON: /api/errors/ba1d1a1e320ddd69. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/FrameworkElementFactory.cs:87

            {
                if (_sealed)
                {
                    throw new InvalidOperationException(SR.Format(SR.CannotChangeAfterSealed, "FrameworkElementFactory"));
                }

                if (_text != null)
                {
                    throw new InvalidOperationException(SR.FrameworkElementFactoryCannotAddText);
                }

                if ( value != null ) // We allow null up until Seal
                {
                    // If non-null, must be derived from one of the supported types
                    if (!typeof(FrameworkElement).IsAssignableFrom(value) &&
                        !typeof(FrameworkContentElement).IsAssignableFrom(value) &&
                        !typeof(Visual3D).IsAssignableFrom(value))
                    {
                        throw new ArgumentException(SR.Format(SR.MustBeFrameworkOr3DDerived, value.Name));
                    }
                }

                // It is possible that _type is null when a FEF is created for text content within a tag
                _type = value;

                // If this is a KnownType in the BamlSchemaContext, then there is a faster way to create
                // an instance of that type than using Activator.CreateInstance.  So in that case
                // save the delegate for later creation.
                WpfKnownType knownType = null;
                if (_type != null)
                {
                    knownType = XamlReader.BamlSharedSchemaContext.GetKnownXamlType(_type) as WpfKnownType;
                }
                _knownTypeFactory = knownType?.DefaultConstructor;
            }
        }

View on GitHub (pinned to 81131a70a4)