diff --git a/src/Avalonia.Base/Interactivity/EventRoute.cs b/src/Avalonia.Base/Interactivity/EventRoute.cs index 3491465a68..37539a7153 100644 --- a/src/Avalonia.Base/Interactivity/EventRoute.cs +++ b/src/Avalonia.Base/Interactivity/EventRoute.cs @@ -143,10 +143,7 @@ namespace Avalonia.Interactivity // If we've got to a new control then call any RoutedEvent.Raised listeners. if (entry.Target != lastTarget) { - if (!e.Handled) - { - _event.InvokeRaised(entry.Target, e); - } + _event.InvokeRaised(entry.Target, e); // If this is a direct event and we've already raised events then we're finished. if (e.Route == RoutingStrategies.Direct && lastTarget is object) diff --git a/tests/Avalonia.Base.UnitTests/Interactivity/InteractiveTests.cs b/tests/Avalonia.Base.UnitTests/Interactivity/InteractiveTests.cs index 1a8b72d5e5..49119c3830 100644 --- a/tests/Avalonia.Base.UnitTests/Interactivity/InteractiveTests.cs +++ b/tests/Avalonia.Base.UnitTests/Interactivity/InteractiveTests.cs @@ -337,6 +337,27 @@ namespace Avalonia.Base.UnitTests.Interactivity Assert.True(target.GetVisualParent().ClassHandlerInvoked); } + [Fact] + public void Typed_Class_Handlers_Should_Be_Called_For_Handled_Events() + { + var ev = new RoutedEvent( + "test", + RoutingStrategies.Bubble | RoutingStrategies.Tunnel, + typeof(TestInteractive)); + + var target = CreateTree(ev, null, 0); + + ev.AddClassHandler((x, e) => x.MarkEventAsHandled(e), RoutingStrategies.Bubble); + ev.AddClassHandler((x, e) => x.ClassHandler(e), RoutingStrategies.Bubble, handledEventsToo: true); + + var args = new RoutedEventArgs(ev, target); + target.RaiseEvent(args); + + Assert.True(args.Handled); + Assert.True(target.ClassHandlerInvoked); + Assert.True(target.GetVisualParent().ClassHandlerInvoked); + } + [Fact] public void GetObservable_Should_Listen_To_Event() { @@ -443,6 +464,11 @@ namespace Avalonia.Base.UnitTests.Interactivity { ClassHandlerInvoked = true; } + + public void MarkEventAsHandled(RoutedEventArgs e) + { + e.Handled = true; + } } } }