From 379d43d553b3578e4424df93600d9c395ae2e4e2 Mon Sep 17 00:00:00 2001 From: TheXamlGuy Date: Sun, 29 Sep 2024 15:01:02 +0100 Subject: [PATCH] Added an EventListenerBehaviour for listening for events raised from the source --- .../AttachedEventTriggerBehaviour.cs | 3 +- Toolkit.UI.Avalonia/EventListenerBehaviour.cs | 133 ++++++++++++++++++ .../KeyBindingTriggerBehaviour.cs | 9 -- 3 files changed, 135 insertions(+), 10 deletions(-) create mode 100644 Toolkit.UI.Avalonia/EventListenerBehaviour.cs diff --git a/Toolkit.UI.Avalonia/AttachedEventTriggerBehaviour.cs b/Toolkit.UI.Avalonia/AttachedEventTriggerBehaviour.cs index 25cb5fd..8c6526d 100644 --- a/Toolkit.UI.Avalonia/AttachedEventTriggerBehaviour.cs +++ b/Toolkit.UI.Avalonia/AttachedEventTriggerBehaviour.cs @@ -4,7 +4,8 @@ using Avalonia.Xaml.Interactivity; namespace Toolkit.UI.Avalonia; -public class AttachedEventTriggerBehaviour : Trigger +public class AttachedEventTriggerBehaviour : + Trigger { public static readonly StyledProperty RoutedEventProperty = AvaloniaProperty.Register(nameof(RoutedEvent)); diff --git a/Toolkit.UI.Avalonia/EventListenerBehaviour.cs b/Toolkit.UI.Avalonia/EventListenerBehaviour.cs new file mode 100644 index 0000000..83ec6f7 --- /dev/null +++ b/Toolkit.UI.Avalonia/EventListenerBehaviour.cs @@ -0,0 +1,133 @@ +using Avalonia; +using Avalonia.Xaml.Interactivity; +using System.Reactive; +using System.Reflection; + +namespace Toolkit.UI.Avalonia; + +public class EventListenerBehaviour : + Trigger +{ + public static readonly StyledProperty EventNameProperty = + AvaloniaProperty.Register(nameof(EventName)); + + public static readonly StyledProperty SourceProperty = + AvaloniaProperty.Register(nameof(Source)); + + private Delegate? eventHandler; + private object? resolvedSource; + + static EventListenerBehaviour() + { + EventNameProperty.Changed.Subscribe(new AnonymousObserver>(EventNamePropertyChanged)); + SourceProperty.Changed.Subscribe(new AnonymousObserver>(SourcePropertyChanged)); + } + + public string EventName + { + get => GetValue(EventNameProperty); + set => SetValue(EventNameProperty, value); + } + + public object Source + { + get => GetValue(SourceProperty); + set => SetValue(SourceProperty, value); + } + + private static void EventNamePropertyChanged(AvaloniaPropertyChangedEventArgs args) + { + if (args.Sender is EventListenerBehaviour behaviour) + { + if (args.OldValue.GetValueOrDefault() is string oldValue) + { + behaviour.UnregisterEvent(oldValue); + } + + if (args.NewValue.GetValueOrDefault() is string newValue) + { + behaviour.RegisterEvent(newValue); + } + } + } + + private static void SourcePropertyChanged(AvaloniaPropertyChangedEventArgs args) + { + if (args.Sender is EventListenerBehaviour behaviour) + { + behaviour.SetResolvedSource(args.GetNewValue()); + } + } + + + private void OnEventRaised(object? sender, EventArgs args) + { + if (IsEnabled) + { + Interaction.ExecuteActions(AssociatedObject, Actions, null); + } + } + + private void RegisterEvent(string eventName) + { + if (eventName is { Length: 0 }) + { + return; + } + + if (resolvedSource is null) + { + return; + } + + Type sourceType = resolvedSource.GetType(); + if (sourceType.GetEvent(EventName) is EventInfo eventInfo) + { + eventInfo.AddEventHandler(resolvedSource, new EventHandler(OnEventRaised)); + } + } + + private void SetResolvedSource(object? newSource) + { + if (resolvedSource == newSource) + { + return; + } + + if (resolvedSource is not null) + { + UnregisterEvent(EventName); + } + + resolvedSource = newSource; + + if (resolvedSource is not null) + { + RegisterEvent(EventName); + } + } + + private void UnregisterEvent(string eventName) + { + if (eventHandler is null) + { + return; + } + + if (eventName is { Length: 0 }) + { + return; + } + + if (resolvedSource is null) + { + return; + } + + Type sourceType = resolvedSource.GetType(); + if (sourceType.GetEvent(EventName) is EventInfo eventInfo) + { + eventInfo.RemoveEventHandler(resolvedSource, new EventHandler(OnEventRaised)); + } + } +} diff --git a/Toolkit.UI.Avalonia/KeyBindingTriggerBehaviour.cs b/Toolkit.UI.Avalonia/KeyBindingTriggerBehaviour.cs index 6d506f6..ef45513 100644 --- a/Toolkit.UI.Avalonia/KeyBindingTriggerBehaviour.cs +++ b/Toolkit.UI.Avalonia/KeyBindingTriggerBehaviour.cs @@ -12,21 +12,12 @@ public class KeyBindingTriggerBehaviour : public static readonly StyledProperty GestureProperty = AvaloniaProperty.Register(nameof(Gesture)); - public static readonly StyledProperty IsEnabledProperty = - AvaloniaProperty.Register(nameof(IsEnabled), true); - public KeyGesture Gesture { get => GetValue(GestureProperty); set => SetValue(GestureProperty, value); } - public bool IsEnabled - { - get => GetValue(IsEnabledProperty); - set => SetValue(IsEnabledProperty, value); - } - public event EventHandler? CanExecuteChanged; protected override void OnAttached()