dotnet/wpf · error · ArgumentException

SR.Format(SR.ReadOnlyPropertyNotAllowed, dp.Name…

Error message

SR.Format(SR.ReadOnlyPropertyNotAllowed, dp.Name, GetType().Name)

What it means

FrameworkElementFactory.SetValue throws ArgumentException when the dependency property is read-only (dp.ReadOnly). Read-only properties are never consulted through the factory because their values are computed by the framework, so rather than silently ignoring the call WPF throws. The message names the property and the factory type.

Solutions

  1. Remove the SetValue call for the read-only property.
  2. If you need to influence the value, set the underlying input property (the one the read-only DP is computed from) instead.
  3. If a settable equivalent exists (non-readonly registration), target that property.

Example fix

// before
factory.SetValue(TextBox.IsReadOnlyPropertyCoreReadOnly, true);
// after
factory.SetValue(TextBox.IsReadOnlyProperty, true); // settable DP
Defensive patterns

Strategy: validation

Validate before calling

if (dp.ReadOnly) throw new InvalidOperationException($"{dp.Name} is read-only; remove the SetValue call.");

Type guard

static bool IsSettable(DependencyProperty dp) => !dp.ReadOnly;

Try / catch

try { factory.SetValue(dp, value); }
catch (ArgumentException ex) when (dp.ReadOnly) { log.LogWarning(ex.Message); }

Prevention

When it happens

Trigger: Calling factory.SetValue(SomeReadOnlyProperty, value), e.g. setting properties registered with DependencyProperty.RegisterReadOnly such as ActualWidth-like or ItemsSource-derived DPs.

Common situations: Copy-pasting SetValue calls from element code into factory code without noticing the target DP is read-only; attempting to 'pre-set' a computed property on template children.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

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

            // 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 )
            {
                resourceKey = dynamicResourceExtension.ResourceKey;
            }

            if (resourceKey == null)
            {
                TemplateBindingExtension templateBinding = value as TemplateBindingExtension;

View on GitHub (pinned to 81131a70a4)