stride3d/stride · error · NotImplementedException

TODO: several events found, find a way to decide the most…

Error message

TODO: several events found, find a way to decide the most relevant one.

What it means

OnEventBehavior.OnAttached throws NotImplementedException when more than one routed event with the same name matches the event owner type. The library cannot decide which routed event is the most relevant to subscribe to. This is an intentional unfinished-code guard, not an expected runtime condition.

Solutions

  1. Use a more specific EventName that does not collide with other routed events.
  2. Set EventOwnerType explicitly to disambiguate which owning type's event should be used.
  3. Avoid attaching the behavior to the UIElement path; use the CLR-event path instead.
  4. Patch the library to pick the closest owner type in the hierarchy.

Example fix

// before
<behaviors:OnEventBehavior EventName="Changed" /> <!-- ambiguous routed event -->
// after
<behaviors:OnEventBehavior EventName="Changed" EventOwnerType="{x:Type local:MyControl}" />
Defensive patterns

Strategy: fallback

Validate before calling

var matches = EventManager.GetRoutedEvents()
    .Where(x => x.Name == eventName && x.OwnerType.IsAssignableFrom(ownerType)).ToArray();
if (matches.Length > 1)
    logger.Warn($"EventName '{eventName}' is ambiguous: {matches.Length} routed events match.");

Type guard

static bool IsUnambiguousRoutedEvent(string eventName, Type ownerType) =>
    EventManager.GetRoutedEvents().Count(x => x.Name == eventName && x.OwnerType.IsAssignableFrom(ownerType)) == 1;

Try / catch

try
{
    element.Behaviors.Add(behavior);
}
catch (NotImplementedException ex) when (ex.Message.Contains("several events"))
{
    logger.Error(ex, $"Ambiguous routed event '{behavior.EventName}'; set EventOwnerType");
}

Prevention

When it happens

Trigger: Attaching the behavior to a UIElement when EventManager.GetRoutedEvents() contains multiple RoutedEvents with the same Name whose OwnerType is assignable from the event owner type (e.g. name collision across class hierarchies).

Common situations: Custom or third-party controls defining routed events whose names clash with built-in WPF events; using an ambiguous EventName that exists on both a base class and an attached class.

Related errors


AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/bf56bc32082f6a46. Report an issue: GitHub.

Appendix: source

Thrown at sources/presentation/Stride.Core.Presentation.Wpf/Behaviors/OnEventBehavior.cs:78

        /// </summary>
        protected abstract void OnEvent();

        /// <inheritdoc/>
        protected override void OnAttached()
        {
            if (EventName == null)
                throw new ArgumentException($"The EventName property must be set on behavior '{GetType().FullName}'.");

            var eventOwnerType = EventOwnerType ?? AssociatedObject.GetType();

            var uiElement = AssociatedObject as UIElement;

            var routedEvents = EventManager.GetRoutedEvents().Where(x => x.Name == EventName && x.OwnerType.IsAssignableFrom(eventOwnerType)).ToArray();

            if (uiElement != null && routedEvents.Length > 0)
            {
                if (routedEvents.Length > 1)
                    throw new NotImplementedException("TODO: several events found, find a way to decide the most relevant one.");

                routedEvent = routedEvents.First();
                uiElement.AddHandler(routedEvent, routedEventHandler);
            }
            else
            {
                var eventInfo = AssociatedObject.GetType().GetEvent(EventName);

                if (eventInfo == null)
                    throw new InvalidOperationException($"Impossible to find a valid event named '{EventName}'.");

                eventHandler = AnonymousEventHandler.RegisterEventHandler(eventInfo, AssociatedObject, OnEvent);
            }
        }

        /// <inheritdoc/>
        protected override void OnDetaching()
        {

View on GitHub (pinned to 96fad776d2)