2023-04-04 12:10:23 -06:00

118 lines
3.1 KiB
C#

using Avalonia;
using Avalonia.Controls;
using Avalonia.Data;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Media;
using Avalonia.Styling;
using System;
using System.Windows.Input;
namespace LibationAvalonia.Controls
{
public partial class LinkLabel : TextBlock, IStyleable, ICommandSource
{
Type IStyleable.StyleKey => typeof(LinkLabel);
public static readonly StyledProperty<ICommand> CommandProperty =
AvaloniaProperty.Register<LinkLabel, ICommand>(nameof(Command), enableDataValidation: true);
public static readonly StyledProperty<object> CommandParameterProperty =
AvaloniaProperty.Register<LinkLabel, object>(nameof(CommandParameter));
public static readonly StyledProperty<IBrush> ForegroundVisitedProperty =
AvaloniaProperty.Register<LinkLabel, IBrush>(nameof(ForegroundVisited));
public static readonly RoutedEvent<RoutedEventArgs> ClickEvent =
RoutedEvent.Register<Button, RoutedEventArgs>(nameof(Click), RoutingStrategies.Bubble);
public ICommand Command
{
get => GetValue(CommandProperty);
set => SetValue(CommandProperty, value);
}
public object CommandParameter
{
get => GetValue(CommandParameterProperty);
set => SetValue(CommandParameterProperty, value);
}
public IBrush ForegroundVisited
{
get => GetValue(ForegroundVisitedProperty);
set => SetValue(ForegroundVisitedProperty, value);
}
public event EventHandler<RoutedEventArgs> Click
{
add => AddHandler(ClickEvent, value);
remove => RemoveHandler(ClickEvent, value);
}
private static readonly Cursor HandCursor = new Cursor(StandardCursorType.Hand);
private bool _commandCanExecute = true;
public LinkLabel()
{
InitializeComponent();
Tapped += LinkLabel_Tapped;
}
private void LinkLabel_Tapped(object sender, TappedEventArgs e)
{
Foreground = ForegroundVisited;
if (IsEffectivelyEnabled)
{
var args = new RoutedEventArgs(ClickEvent);
RaiseEvent(args);
if (!args.Handled && Command?.CanExecute(CommandParameter) == true)
{
Command.Execute(CommandParameter);
args.Handled = true;
}
}
}
protected override void OnPointerEntered(PointerEventArgs e)
{
this.Cursor = HandCursor;
base.OnPointerEntered(e);
}
protected override void OnPointerExited(PointerEventArgs e)
{
this.Cursor = Cursor.Default;
base.OnPointerExited(e);
}
protected override bool IsEnabledCore => base.IsEnabledCore && _commandCanExecute;
protected override void UpdateDataValidation(AvaloniaProperty property, BindingValueType state, Exception error)
{
base.UpdateDataValidation(property, state, error);
if (property == CommandProperty)
{
if (state == BindingValueType.BindingError)
{
if (_commandCanExecute)
{
_commandCanExecute = false;
UpdateIsEffectivelyEnabled();
}
}
}
}
public void CanExecuteChanged(object sender, EventArgs e)
{
var canExecute = Command == null || Command.CanExecute(CommandParameter);
if (canExecute != _commandCanExecute)
{
_commandCanExecute = canExecute;
UpdateIsEffectivelyEnabled();
}
}
}
}