dotnet/wpf · error · NotSupportedException

SR.Format(SR.ModifyingLogicalTreeViaStylesNotImplemented…

Error message

SR.Format(SR.ModifyingLogicalTreeViaStylesNotImplemented, value, "FrameworkElementFactory.SetValue")

What it means

FrameworkElementFactory.SetValue throws NotSupportedException when the value would modify (style) the logical tree. Values such as elements or logical-tree-touching references are not allowed to be set through a style factory because styles must not reparent or modify the logical tree. WPF deliberately disallows this scenario rather than producing undefined behavior at instantiation.

Solutions

  1. Use factory.AppendChild(childFactory) with a nested FrameworkElementFactory instead of SetValue with an element.
  2. Set logical-tree properties after template instantiation on the actual element instance.
  3. If a plain value is intended, verify you are passing a value object, not a UIElement, to SetValue.

Example fix

// before
factory.SetValue(ContentPresenter.ContentProperty, new TextBlock());
// after
var textFactory = new FrameworkElementFactory(typeof(TextBlock));
factory.AppendChild(textFactory);
Defensive patterns

Strategy: validation

Validate before calling

if (value is UIElement) throw new InvalidOperationException("Use AppendChild, not SetValue, for logical-tree values.");

Type guard

static bool IsLogicalTreeValue(object value) => value is UIElement or ContentElement;

Try / catch

try { factory.SetValue(dp, value); }
catch (NotSupportedException) { var child = new FrameworkElementFactory(value.GetType()); factory.AppendChild(child); }

Prevention

When it happens

Trigger: Calling factory.SetValue(dp, value) where StyleHelper.IsStylingLogicalTree(dp, value) returns true — typically setting a property to a UIElement or a value that would be added to the logical tree via the style.

Common situations: Trying to set a Content or Child property to an element instance on a FrameworkElementFactory; attempting to embed child visuals via factory SetValue instead of AddChild; code translated from templates that worked with direct element construction.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

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

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

            ArgumentNullException.ThrowIfNull(dp);

            // Value needs to be valid for the DP, or Binding/MultiBinding/PriorityBinding.
            //  (They all have MarkupExtension, which we don't actually support, see above check.)

            if (!dp.IsValidValue(value) && !(value is MarkupExtension) && !(value is DeferredReference))
            {
                throw new ArgumentException(SR.Format(SR.InvalidPropertyValue, value, dp.Name));
            }

            // Styling the logical tree is not supported
            if (StyleHelper.IsStylingLogicalTree(dp, value))
            {
                throw new NotSupportedException(SR.Format(SR.ModifyingLogicalTreeViaStylesNotImplemented, value, "FrameworkElementFactory.SetValue"));
            }

            if (dp.ReadOnly)
            {
                // Read-only properties will not be consulting FrameworkElementFactory for value.
                //  Rather than silently do nothing, throw error.
                throw new ArgumentException(SR.Format(SR.ReadOnlyPropertyNotAllowed, dp.Name, GetType().Name));
            }

            ResourceReferenceExpression resourceExpression = value as ResourceReferenceExpression;
            DynamicResourceExtension dynamicResourceExtension = value as DynamicResourceExtension;
            object resourceKey = null;

            if( resourceExpression != null )
            {
                resourceKey = resourceExpression.ResourceKey;
            }
            else if( dynamicResourceExtension != null )

View on GitHub (pinned to 81131a70a4)