dotnet/wpf · error · ArgumentException

SR.TextRange_InvalidParameterValue

Error message

SR.TextRange_InvalidParameterValue

What it means

EventSetterHandlerConverter.ConvertFrom converts XAML string handler names into delegates, but only when invoked by the XAML parser. It throws ArgumentException with TextRange_InvalidParameterValue when the typeDescriptorContext is not MS.Internal.Xaml.ServiceProviderContext, deliberately refusing to hand a delegate to arbitrary callers (security measure).

Solutions

  1. Do not call this converter directly; let the WPF XAML parser process the EventSetter Handler attribute
  2. In code, construct the delegate yourself: new RoutedEventHandler(OnClick)
  3. If building tooling, replicate the parser behavior: resolve the method on the root object and create the delegate explicitly

Example fix

// before
var del = converter.ConvertFrom(ctx, culture, "OnClick"); // throws (ctx is not XAML context)
// after
var del = new RoutedEventHandler(OnClick);
Defensive patterns

Strategy: type-guard

Validate before calling

// Do not call this converter from application code; construct delegates directly.

Type guard

bool IsXamlParserContext(ITypeDescriptorContext ctx) =>
    ctx?.GetType().FullName == "MS.Internal.Xaml.ServiceProviderContext";

Try / catch

try { result = converter.ConvertFrom(ctx, culture, handlerName); }
catch (ArgumentException ex) when (ex.ParamName == "typeDescriptorContext") { result = null; }

Prevention

When it happens

Trigger: Calling EventSetterHandlerConverter.ConvertFrom directly (or from custom tooling) with a plain ITypeDescriptorContext that is not the XAML parser's ServiceProviderContext.

Common situations: Custom XAML readers/designers, serialization utilities, or unit tests invoking the converter directly instead of letting the WPF XAML parser process the Handler attribute.

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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/EventSetterHandlerConverter.cs:62

        ///     Convert a string like "Button.Click" into the corresponding RoutedEvent
        /// </summary>
        public override object ConvertFrom(ITypeDescriptorContext typeDescriptorContext,
                                           CultureInfo cultureInfo,
                                           object source)
        {
            ArgumentNullException.ThrowIfNull(typeDescriptorContext);
            ArgumentNullException.ThrowIfNull(source);
            if (s_ServiceProviderContextType == null)
            {
                // get typeof(MS.Internal.Xaml.ServiceProviderContext) via reflection
                Assembly a = typeof(IRootObjectProvider).Assembly;
                s_ServiceProviderContextType = a.GetType("MS.Internal.Xaml.ServiceProviderContext");
            }
            if (typeDescriptorContext.GetType() != s_ServiceProviderContextType)
            {
                // if the caller is not the XAML parser, don't answer.   This avoids
                // returning an arbitrary delegate to a (possibly malicious) caller.
                throw new ArgumentException(SR.TextRange_InvalidParameterValue, nameof(typeDescriptorContext));
            }
            IRootObjectProvider rootProvider = typeDescriptorContext.GetService(typeof(IRootObjectProvider)) as IRootObjectProvider;
            if (rootProvider != null && source is String)
            {
                IProvideValueTarget ipvt = typeDescriptorContext.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget;
                if (ipvt != null)
                {
                    EventSetter setter = ipvt.TargetObject as EventSetter;
                    string handlerName;
                    if(setter != null && (handlerName = source as string) != null)
                    {
                        handlerName = handlerName.Trim();
                        return Delegate.CreateDelegate(setter.Event.HandlerType, rootProvider.RootObject, handlerName);
                    }
                }
            }

            throw GetConvertFromException(source);

View on GitHub (pinned to 81131a70a4)