using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Reactive;
using Avalonia.Xaml.Interactivity;
namespace Avalonia.Xaml.Interactions.Custom;
///
/// A behavior that listens for a event on its source and executes its actions when that event is fired.
///
public class RoutedEventTriggerBehavior : StyledElementTrigger
{
///
/// Identifies the avalonia property.
///
public static readonly StyledProperty RoutedEventProperty =
AvaloniaProperty.Register(nameof(RoutedEvent));
///
/// Identifies the avalonia property.
///
public static readonly StyledProperty RoutingStrategiesProperty =
AvaloniaProperty.Register(nameof(RoutingStrategies),
RoutingStrategies.Direct | RoutingStrategies.Bubble);
///
/// Identifies the avalonia property.
///
public static readonly StyledProperty SourceInteractiveProperty =
AvaloniaProperty.Register(nameof(SourceInteractive));
private bool _isInitialized;
private bool _isAttached;
///
/// Gets or sets routing event to listen for. This is a avalonia property.
///
public RoutedEvent? RoutedEvent
{
get => GetValue(RoutedEventProperty);
set => SetValue(RoutedEventProperty, value);
}
///
/// Gets or sets the routing event . This is a avalonia property.
///
public RoutingStrategies RoutingStrategies
{
get => GetValue(RoutingStrategiesProperty);
set => SetValue(RoutingStrategiesProperty, value);
}
///
/// Gets or sets the source object from which this behavior listens for events.
/// If is not set, the source will default to . This is a avalonia property.
///
[ResolveByName]
public Interactive? SourceInteractive
{
get => GetValue(SourceInteractiveProperty);
set => SetValue(SourceInteractiveProperty, value);
}
static RoutedEventTriggerBehavior()
{
RoutedEventProperty.Changed.Subscribe(
new AnonymousObserver>(OnValueChanged));
RoutingStrategiesProperty.Changed.Subscribe(
new AnonymousObserver>(OnValueChanged));
SourceInteractiveProperty.Changed.Subscribe(
new AnonymousObserver>(OnValueChanged));
}
private static void OnValueChanged(AvaloniaPropertyChangedEventArgs args)
{
if (args.Sender is not RoutedEventTriggerBehavior behavior || behavior.AssociatedObject is null)
{
return;
}
if (behavior._isInitialized && behavior._isAttached)
{
behavior.RemoveHandler();
behavior.AddHandler();
}
}
///
protected override void OnAttachedToVisualTree()
{
_isAttached = true;
AddHandler();
}
///
protected override void OnDetachedFromVisualTree()
{
_isAttached = false;
RemoveHandler();
}
private void AddHandler()
{
var interactive = ComputeResolvedSourceInteractive();
if (interactive is not null && RoutedEvent is not null)
{
interactive.AddHandler(RoutedEvent, Handler, RoutingStrategies);
_isInitialized = true;
}
}
private void RemoveHandler()
{
var interactive = ComputeResolvedSourceInteractive();
if (interactive is not null && RoutedEvent is not null && _isInitialized)
{
interactive.RemoveHandler(RoutedEvent, Handler);
_isInitialized = false;
}
}
private Interactive? ComputeResolvedSourceInteractive()
{
return GetValue(SourceInteractiveProperty) is not null ? SourceInteractive : AssociatedObject;
}
private void Handler(object? sender, RoutedEventArgs e)
{
if (!IsEnabled)
{
return;
}
var interactive = ComputeResolvedSourceInteractive();
if (interactive is not null)
{
Interaction.ExecuteActions(interactive, Actions, e);
}
}
}