|
|
|
@ -59,13 +59,13 @@ namespace Avalonia.Controls |
|
|
|
AvaloniaProperty.Register<Button, object>(nameof(CommandParameter)); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Defines the <see cref="IsDefault"/> property.
|
|
|
|
/// Defines the <see cref="IsDefaultProperty"/> property.
|
|
|
|
/// </summary>
|
|
|
|
public static readonly StyledProperty<bool> IsDefaultProperty = |
|
|
|
AvaloniaProperty.Register<Button, bool>(nameof(IsDefault)); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Defines the <see cref="IsCancel"/> property.
|
|
|
|
/// Defines the <see cref="IsCancelProperty"/> property.
|
|
|
|
/// </summary>
|
|
|
|
public static readonly StyledProperty<bool> IsCancelProperty = |
|
|
|
AvaloniaProperty.Register<Button, bool>(nameof(IsCancel)); |
|
|
|
@ -98,6 +98,10 @@ namespace Avalonia.Controls |
|
|
|
static Button() |
|
|
|
{ |
|
|
|
FocusableProperty.OverrideDefaultValue(typeof(Button), true); |
|
|
|
CommandProperty.Changed.Subscribe(CommandChanged); |
|
|
|
CommandParameterProperty.Changed.Subscribe(CommandParameterChanged); |
|
|
|
IsDefaultProperty.Changed.Subscribe(IsDefaultChanged); |
|
|
|
IsCancelProperty.Changed.Subscribe(IsCancelChanged); |
|
|
|
AccessKeyHandler.AccessKeyPressedEvent.AddClassHandler<Button>((lbl, args) => lbl.OnAccessKey(args)); |
|
|
|
} |
|
|
|
|
|
|
|
@ -386,88 +390,116 @@ namespace Avalonia.Controls |
|
|
|
{ |
|
|
|
base.OnPropertyChanged(change); |
|
|
|
|
|
|
|
if (change.Property == CommandProperty) |
|
|
|
if (change.Property == IsPressedProperty) |
|
|
|
{ |
|
|
|
if (((ILogical)this).IsAttachedToLogicalTree) |
|
|
|
{ |
|
|
|
if (change.OldValue.GetValueOrDefault() is ICommand oldCommand) |
|
|
|
{ |
|
|
|
oldCommand.CanExecuteChanged -= CanExecuteChanged; |
|
|
|
} |
|
|
|
|
|
|
|
if (change.NewValue.GetValueOrDefault() is ICommand newCommand) |
|
|
|
{ |
|
|
|
newCommand.CanExecuteChanged += CanExecuteChanged; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
CanExecuteChanged(this, EventArgs.Empty); |
|
|
|
UpdatePseudoClasses(change.NewValue.GetValueOrDefault<bool>()); |
|
|
|
} |
|
|
|
else if (change.Property == CommandParameterProperty) |
|
|
|
else if (change.Property == FlyoutProperty) |
|
|
|
{ |
|
|
|
CanExecuteChanged(this, EventArgs.Empty); |
|
|
|
// If flyout is changed while one is already open, make sure we
|
|
|
|
// close the old one first
|
|
|
|
if (change.OldValue.GetValueOrDefault() is FlyoutBase oldFlyout && |
|
|
|
oldFlyout.IsOpen) |
|
|
|
{ |
|
|
|
oldFlyout.Hide(); |
|
|
|
} |
|
|
|
} |
|
|
|
else if (change.Property == IsCancelProperty) |
|
|
|
{ |
|
|
|
var isCancel = change.NewValue.GetValueOrDefault<bool>(); |
|
|
|
} |
|
|
|
|
|
|
|
if (VisualRoot is IInputElement inputRoot) |
|
|
|
/// <inheritdoc/>
|
|
|
|
protected override void UpdateDataValidation<T>(AvaloniaProperty<T> property, BindingValue<T> value) |
|
|
|
{ |
|
|
|
base.UpdateDataValidation(property, value); |
|
|
|
if (property == CommandProperty) |
|
|
|
{ |
|
|
|
if (value.Type == BindingValueType.BindingError) |
|
|
|
{ |
|
|
|
if (isCancel) |
|
|
|
{ |
|
|
|
ListenForCancel(inputRoot); |
|
|
|
} |
|
|
|
else |
|
|
|
if (_commandCanExecute) |
|
|
|
{ |
|
|
|
StopListeningForCancel(inputRoot); |
|
|
|
_commandCanExecute = false; |
|
|
|
UpdateIsEffectivelyEnabled(); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
else if (change.Property == IsDefaultProperty) |
|
|
|
{ |
|
|
|
var isDefault = change.NewValue.GetValueOrDefault<bool>(); |
|
|
|
} |
|
|
|
|
|
|
|
if (VisualRoot is IInputElement inputRoot) |
|
|
|
/// <summary>
|
|
|
|
/// Called when the <see cref="Command"/> property changes.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="e">The event args.</param>
|
|
|
|
private static void CommandChanged(AvaloniaPropertyChangedEventArgs e) |
|
|
|
{ |
|
|
|
if (e.Sender is Button button) |
|
|
|
{ |
|
|
|
if (((ILogical)button).IsAttachedToLogicalTree) |
|
|
|
{ |
|
|
|
if (isDefault) |
|
|
|
if (e.OldValue is ICommand oldCommand) |
|
|
|
{ |
|
|
|
ListenForDefault(inputRoot); |
|
|
|
oldCommand.CanExecuteChanged -= button.CanExecuteChanged; |
|
|
|
} |
|
|
|
else |
|
|
|
|
|
|
|
if (e.NewValue is ICommand newCommand) |
|
|
|
{ |
|
|
|
StopListeningForDefault(inputRoot); |
|
|
|
newCommand.CanExecuteChanged += button.CanExecuteChanged; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
button.CanExecuteChanged(button, EventArgs.Empty); |
|
|
|
} |
|
|
|
else if (change.Property == IsPressedProperty) |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Called when the <see cref="CommandParameter"/> property changes.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="e">The event args.</param>
|
|
|
|
private static void CommandParameterChanged(AvaloniaPropertyChangedEventArgs e) |
|
|
|
{ |
|
|
|
if (e.Sender is Button button) |
|
|
|
{ |
|
|
|
UpdatePseudoClasses(change.NewValue.GetValueOrDefault<bool>()); |
|
|
|
button.CanExecuteChanged(button, EventArgs.Empty); |
|
|
|
} |
|
|
|
else if (change.Property == FlyoutProperty) |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Called when the <see cref="IsDefault"/> property changes.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="e">The event args.</param>
|
|
|
|
private static void IsDefaultChanged(AvaloniaPropertyChangedEventArgs e) |
|
|
|
{ |
|
|
|
var button = e.Sender as Button; |
|
|
|
var isDefault = (bool)e.NewValue; |
|
|
|
|
|
|
|
if (button?.VisualRoot is IInputElement inputRoot) |
|
|
|
{ |
|
|
|
// If flyout is changed while one is already open, make sure we
|
|
|
|
// close the old one first
|
|
|
|
if (change.OldValue.GetValueOrDefault() is FlyoutBase oldFlyout && |
|
|
|
oldFlyout.IsOpen) |
|
|
|
if (isDefault) |
|
|
|
{ |
|
|
|
oldFlyout.Hide(); |
|
|
|
button.ListenForDefault(inputRoot); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
button.StopListeningForDefault(inputRoot); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/// <inheritdoc/>
|
|
|
|
protected override void UpdateDataValidation<T>(AvaloniaProperty<T> property, BindingValue<T> value) |
|
|
|
/// <summary>
|
|
|
|
/// Called when the <see cref="IsCancel"/> property changes.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="e">The event args.</param>
|
|
|
|
private static void IsCancelChanged(AvaloniaPropertyChangedEventArgs e) |
|
|
|
{ |
|
|
|
base.UpdateDataValidation(property, value); |
|
|
|
if (property == CommandProperty) |
|
|
|
var button = e.Sender as Button; |
|
|
|
var isCancel = (bool)e.NewValue; |
|
|
|
|
|
|
|
if (button?.VisualRoot is IInputElement inputRoot) |
|
|
|
{ |
|
|
|
if (value.Type == BindingValueType.BindingError) |
|
|
|
if (isCancel) |
|
|
|
{ |
|
|
|
if (_commandCanExecute) |
|
|
|
{ |
|
|
|
_commandCanExecute = false; |
|
|
|
UpdateIsEffectivelyEnabled(); |
|
|
|
} |
|
|
|
button.ListenForCancel(inputRoot); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
button.StopListeningForCancel(inputRoot); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|