@ -64,6 +64,12 @@ namespace Avalonia.Controls
public static readonly StyledProperty < bool > IsDefaultProperty =
AvaloniaProperty . Register < Button , bool > ( nameof ( IsDefault ) ) ;
/// <summary>
/// Defines the <see cref="IsCancelProperty"/> property.
/// </summary>
public static readonly StyledProperty < bool > IsCancelProperty =
AvaloniaProperty . Register < Button , bool > ( nameof ( IsCancel ) ) ;
/// <summary>
/// Defines the <see cref="Click"/> event.
/// </summary>
@ -84,6 +90,7 @@ namespace Avalonia.Controls
FocusableProperty . OverrideDefaultValue ( typeof ( Button ) , true ) ;
CommandProperty . Changed . Subscribe ( CommandChanged ) ;
IsDefaultProperty . Changed . Subscribe ( IsDefaultChanged ) ;
IsCancelProperty . Changed . Subscribe ( IsCancelChanged ) ;
PseudoClass < Button > ( IsPressedProperty , ":pressed" ) ;
}
@ -142,6 +149,16 @@ namespace Avalonia.Controls
set { SetValue ( IsDefaultProperty , value ) ; }
}
/// <summary>
/// Gets or sets a value indicating whether the button is the Cancel button for the
/// window.
/// </summary>
public bool IsCancel
{
get { return GetValue ( IsCancelProperty ) ; }
set { SetValue ( IsCancelProperty , value ) ; }
}
public bool IsPressed
{
get { return GetValue ( IsPressedProperty ) ; }
@ -162,6 +179,13 @@ namespace Avalonia.Controls
ListenForDefault ( inputElement ) ;
}
}
if ( IsCancel )
{
if ( e . Root is IInputElement inputElement )
{
ListenForCancel ( inputElement ) ;
}
}
}
/// <inheritdoc/>
@ -351,6 +375,28 @@ namespace Avalonia.Controls
}
}
/// <summary>
/// Called when the <see cref="IsCancel"/> property changes.
/// </summary>
/// <param name="e">The event args.</param>
private static void IsCancelChanged ( AvaloniaPropertyChangedEventArgs e )
{
var button = e . Sender as Button ;
var isCancel = ( bool ) e . NewValue ;
if ( button ? . VisualRoot is IInputElement inputRoot )
{
if ( isCancel )
{
button . ListenForCancel ( inputRoot ) ;
}
else
{
button . StopListeningForCancel ( inputRoot ) ;
}
}
}
/// <summary>
/// Called when the <see cref="ICommand.CanExecuteChanged"/> event fires.
/// </summary>
@ -373,7 +419,16 @@ namespace Avalonia.Controls
/// <param name="root">The input root.</param>
private void ListenForDefault ( IInputElement root )
{
root . AddHandler ( KeyDownEvent , RootKeyDown ) ;
root . AddHandler ( KeyDownEvent , RootDefaultKeyDown ) ;
}
/// <summary>
/// Starts listening for the Enter key when the button <see cref="IsCancel"/>.
/// </summary>
/// <param name="root">The input root.</param>
private void ListenForCancel ( IInputElement root )
{
root . AddHandler ( KeyDownEvent , RootCancelKeyDown ) ;
}
/// <summary>
@ -382,7 +437,16 @@ namespace Avalonia.Controls
/// <param name="root">The input root.</param>
private void StopListeningForDefault ( IInputElement root )
{
root . RemoveHandler ( KeyDownEvent , RootKeyDown ) ;
root . RemoveHandler ( KeyDownEvent , RootDefaultKeyDown ) ;
}
/// <summary>
/// Stops listening for the Escape key when the button is no longer <see cref="IsCancel"/>.
/// </summary>
/// <param name="root">The input root.</param>
private void StopListeningForCancel ( IInputElement root )
{
root . RemoveHandler ( KeyDownEvent , RootCancelKeyDown ) ;
}
/// <summary>
@ -390,12 +454,25 @@ namespace Avalonia.Controls
/// </summary>
/// <param name="sender">The event sender.</param>
/// <param name="e">The event args.</param>
private void RootKeyDown ( object sender , KeyEventArgs e )
private void RootDefault KeyDown ( object sender , KeyEventArgs e )
{
if ( e . Key = = Key . Enter & & IsVisible & & IsEnabled )
{
OnClick ( ) ;
}
}
/// <summary>
/// Called when a key is pressed on the input root and the button <see cref="IsCancel"/>.
/// </summary>
/// <param name="sender">The event sender.</param>
/// <param name="e">The event args.</param>
private void RootCancelKeyDown ( object sender , KeyEventArgs e )
{
if ( e . Key = = Key . Escape & & IsVisible & & IsEnabled )
{
OnClick ( ) ;
}
}
}
}