dotnet/wpf · error · NotSupportedException

SR.NoMulticastHandlers

Error message

SR.NoMulticastHandlers

What it means

ValueChangedEventManager.AddHandler requires a delegate with exactly one target; multicast (combined) delegates are rejected with NotSupportedException(SR.NoMulticastHandlers). The weak-event manager tracks one target per handler and cannot correctly unsubscribe combined delegates.

Solutions

  1. Register each handler method individually (one AddHandler call per method)
  2. Split the combined delegate into GetInvocationList() and call AddHandler for each single-target delegate
  3. Use a lambda or method group that references only one target

Example fix

// before
EventHandler<ValueChangedEventArgs> h = OnA; h += OnB;
ValueChangedEventManager.AddHandler(source, h, pd); // throws
// after
ValueChangedEventManager.AddHandler(source, OnA, pd);
ValueChangedEventManager.AddHandler(source, OnB, pd);
Defensive patterns

Strategy: validation

Validate before calling

if (handler == null) throw new ArgumentNullException(nameof(handler));
if (handler.GetInvocationList().Length > 1) throw new ArgumentException("Use single-target delegates with ValueChangedEventManager");

Type guard

bool HasSingleTarget(Delegate d) => d is { } && d.GetInvocationList().Length == 1;

Try / catch

if (handler.GetInvocationList().Length == 1)
    ValueChangedEventManager.AddHandler(source, handler, pd);
else
    foreach (EventHandler<ValueChangedEventArgs> h in handler.GetInvocationList())
        ValueChangedEventManager.AddHandler(source, h, pd);

Prevention

When it happens

Trigger: Calling ValueChangedEventManager.AddHandler(source, handler, pd) where handler was built with Delegate.Combine / '+=' on a local delegate variable, giving it multiple invocation targets.

Common situations: Reusing a shared multicast event-handler field for weak-event registration; refactoring from normal CLR events (which allow multicast) to weak events without splitting handlers.

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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/Data/ValueChangedEventManager.cs:87

        /// <summary>
        /// Remove a listener to the given source's event.
        /// </summary>
        public static void RemoveListener(object source, IWeakEventListener listener, PropertyDescriptor pd)
        {
            ArgumentNullException.ThrowIfNull(source);
            ArgumentNullException.ThrowIfNull(listener);

            CurrentManager.PrivateRemoveListener(source, listener, pd);
        }

        /// <summary>
        /// Add a handler for the given source's event.
        /// </summary>
        public static void AddHandler(object source, EventHandler<ValueChangedEventArgs> handler, PropertyDescriptor pd)
        {
            ArgumentNullException.ThrowIfNull(handler);
            if (!handler.HasSingleTarget)
                throw new NotSupportedException(SR.NoMulticastHandlers);

            CurrentManager.PrivateAddHandler(source, handler, pd);
        }

        /// <summary>
        /// Remove a handler for the given source's event.
        /// </summary>
        public static void RemoveHandler(object source, EventHandler<ValueChangedEventArgs> handler, PropertyDescriptor pd)
        {
            ArgumentNullException.ThrowIfNull(handler);
            if (!handler.HasSingleTarget)
                throw new NotSupportedException(SR.NoMulticastHandlers);

            CurrentManager.PrivateRemoveHandler(source, handler, pd);
        }

        #endregion Public Methods

View on GitHub (pinned to 81131a70a4)