1
0
Эх сурвалжийг харах

added IsCancel to Button

Like pressing Enter triggers a button that has the property IsDefault set to true, pressing Escape should work on the button that has IsCancel set to true.
Tridy 6 жил өмнө
parent
commit
42dd06cf96

+ 80 - 3
src/Avalonia.Controls/Button.cs

@@ -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 RootDefaultKeyDown(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();
+            }
+        }
     }
 }