diff --git a/src/Avalonia.Interactivity/RoutedEvent.cs b/src/Avalonia.Interactivity/RoutedEvent.cs index 61bb567d54..2d752133c1 100644 --- a/src/Avalonia.Interactivity/RoutedEvent.cs +++ b/src/Avalonia.Interactivity/RoutedEvent.cs @@ -72,7 +72,9 @@ namespace Avalonia.Interactivity { Contract.Requires(name != null); - return new RoutedEvent(name, routingStrategy, typeof(TOwner)); + var routedEvent = new RoutedEvent(name, routingStrategy, typeof(TOwner)); + RoutedEventRegistry.Instance.Register(typeof(TOwner), routedEvent); + return routedEvent; } public static RoutedEvent Register( @@ -83,7 +85,9 @@ namespace Avalonia.Interactivity { Contract.Requires(name != null); - return new RoutedEvent(name, routingStrategy, ownerType); + var routedEvent = new RoutedEvent(name, routingStrategy, ownerType); + RoutedEventRegistry.Instance.Register(ownerType, routedEvent); + return routedEvent; } public IDisposable AddClassHandler( diff --git a/src/Avalonia.Interactivity/RoutedEventRegistry.cs b/src/Avalonia.Interactivity/RoutedEventRegistry.cs new file mode 100644 index 0000000000..34c970a806 --- /dev/null +++ b/src/Avalonia.Interactivity/RoutedEventRegistry.cs @@ -0,0 +1,90 @@ +// Copyright (c) The Avalonia Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. + +using System; +using System.Collections.Generic; + +namespace Avalonia.Interactivity +{ + /// + /// Tracks registered s. + /// + public class RoutedEventRegistry + { + private readonly Dictionary> _registeredRoutedEvents = + new Dictionary>(); + + /// + /// Gets the instance. + /// + public static RoutedEventRegistry Instance { get; } + = new RoutedEventRegistry(); + + /// + /// Registers a on a type. + /// + /// The type. + /// The event. + /// + /// You won't usually want to call this method directly, instead use the + /// + /// method. + /// + public void Register(Type type, RoutedEvent @event) + { + Contract.Requires(type != null); + Contract.Requires(@event != null); + + if (!_registeredRoutedEvents.TryGetValue(type, out var list)) + { + list = new List(); + _registeredRoutedEvents.Add(type, list); + } + list.Add(@event); + } + + /// + /// Returns all routed events, that are currently registered in the event registry. + /// + /// All routed events, that are currently registered in the event registry. + public IEnumerable GetAllRegistered() + { + foreach (var events in _registeredRoutedEvents.Values) + { + foreach (var e in events) + { + yield return e; + } + } + } + + /// + /// Returns all routed events registered with the provided type. + /// If the type is not found or does not provide any routed events, an empty list is returned. + /// + /// The type. + /// All routed events registered with the provided type. + public IReadOnlyList GetRegistered(Type type) + { + Contract.Requires(type != null); + + if (_registeredRoutedEvents.TryGetValue(type, out var events)) + { + return events; + } + + return Array.Empty(); + } + + /// + /// Returns all routed events registered with the provided type. + /// If the type is not found or does not provide any routed events, an empty list is returned. + /// + /// The type. + /// All routed events registered with the provided type. + public IReadOnlyList GetRegistered() + { + return GetRegistered(typeof(TOwner)); + } + } +} diff --git a/tests/Avalonia.Interactivity.UnitTests/RoutedEventRegistryTests.cs b/tests/Avalonia.Interactivity.UnitTests/RoutedEventRegistryTests.cs new file mode 100644 index 0000000000..b9ebdea064 --- /dev/null +++ b/tests/Avalonia.Interactivity.UnitTests/RoutedEventRegistryTests.cs @@ -0,0 +1,49 @@ +// Copyright (c) The Avalonia Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. + +using System.Collections.Generic; +using Avalonia.Controls; +using Avalonia.Input; +using Xunit; + +namespace Avalonia.Interactivity.UnitTests +{ + public class RoutedEventRegistryTests + { + [Fact] + public void Pointer_Events_Should_Be_Registered() + { + var expectedEvents = new List { InputElement.PointerPressedEvent, InputElement.PointerReleasedEvent }; + var registeredEvents = RoutedEventRegistry.Instance.GetRegistered(); + Assert.Contains(registeredEvents, expectedEvents.Contains); + } + + [Fact] + public void ClickEvent_Should_Be_Registered_On_Button() + { + var expectedEvents = new List { Button.ClickEvent }; + var registeredEvents = RoutedEventRegistry.Instance.GetRegistered