Improve LinkLabel control

This commit is contained in:
Mbucari 2023-04-04 12:10:23 -06:00
parent 2d2907e076
commit d737cd2199
5 changed files with 94 additions and 8 deletions

View File

@ -1,6 +1,7 @@
<Application xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:LibationAvalonia"
xmlns:controls="using:LibationAvalonia.Controls"
x:Class="LibationAvalonia.App"
Name="Libation">
@ -69,6 +70,10 @@
<Setter Property="Background" Value="{DynamicResource SystemControlBackgroundBaseLowBrush}" />
</Style>
</Style>
<Style Selector="controls|LinkLabel">
<Setter Property="Foreground" Value="{DynamicResource HyperlinkNew}"/>
<Setter Property="ForegroundVisited" Value="{DynamicResource HyperlinkVisited}"/>
</Style>
</Application.Styles>
<NativeMenu.Menu>

View File

@ -27,7 +27,6 @@ namespace LibationAvalonia
public static IBrush ProcessQueueBookCancelledBrush { get; private set; }
public static IBrush ProcessQueueBookDefaultBrush { get; private set; }
public static IBrush SeriesEntryGridBackgroundBrush { get; private set; }
public static IBrush HyperlinkVisited { get; private set; }
public static IAssetLoader AssetLoader { get; private set; }
@ -230,7 +229,6 @@ namespace LibationAvalonia
ProcessQueueBookCancelledBrush = AvaloniaUtils.GetBrushFromResources(nameof(ProcessQueueBookCancelledBrush));
SeriesEntryGridBackgroundBrush = AvaloniaUtils.GetBrushFromResources(nameof(SeriesEntryGridBackgroundBrush));
ProcessQueueBookDefaultBrush = AvaloniaUtils.GetBrushFromResources(nameof(ProcessQueueBookDefaultBrush));
HyperlinkVisited = AvaloniaUtils.GetBrushFromResources(nameof(HyperlinkVisited));
}
}
}

View File

@ -3,10 +3,10 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
xmlns:controls="using:LibationAvalonia.Controls"
x:Class="LibationAvalonia.Controls.LinkLabel">
<TextBlock.Styles>
<Style Selector="TextBlock">
<Setter Property="Foreground" Value="{DynamicResource HyperlinkNew}"/>
<Style Selector="controls|LinkLabel">
<Setter Property="TextDecorations" Value="Underline"/>
</Style>
</TextBlock.Styles>

View File

@ -1,14 +1,57 @@
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
public partial class LinkLabel : TextBlock, IStyleable, ICommandSource
{
Type IStyleable.StyleKey => typeof(TextBlock);
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();
@ -17,7 +60,19 @@ namespace LibationAvalonia.Controls
private void LinkLabel_Tapped(object sender, TappedEventArgs e)
{
Foreground = App.HyperlinkVisited;
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)
@ -30,5 +85,33 @@ namespace LibationAvalonia.Controls
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();
}
}
}
}

View File

@ -54,7 +54,7 @@
<WrapPanel>
<WrapPanel.Styles>
<Style Selector="TextBlock">
<Style Selector="controls|LinkLabel">
<Setter Property="Margin" Value="5,0" />
<Setter Property="FontSize" Value="13" />
</Style>