Browse Source

fix: Navigation when CanExecute is fasle (#13507)

* test: Add test navigation with CanExecute is False

* fix: Navigation when CanExecute is false
UnsafeAsSpan-logical-children
workgroupengineering 3 years ago
committed by GitHub
parent
commit
99737a8395
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      src/Avalonia.Base/Input/Navigation/TabNavigation.cs
  2. 15
      tests/Avalonia.Base.UnitTests/Input/KeyboardDeviceTests.cs
  3. 38
      tests/Avalonia.Base.UnitTests/Input/KeyboardNavigationTests_Tab.cs
  4. 19
      tests/Avalonia.Base.UnitTests/Utilities/DelegateCommand.cs

4
src/Avalonia.Base/Input/Navigation/TabNavigation.cs

@ -649,12 +649,12 @@ namespace Avalonia.Input.Navigation
private static bool IsTabStop(IInputElement e)
{
if (e is InputElement ie)
return ie.Focusable && KeyboardNavigation.GetIsTabStop(ie) && ie.IsVisible && ie.IsEnabled;
return ie.Focusable && KeyboardNavigation.GetIsTabStop(ie) && ie.IsVisible && ie.IsEffectivelyEnabled;
return false;
}
private static bool IsTabStopOrGroup(IInputElement e) => IsTabStop(e) || IsGroup(e);
private static bool IsVisible(IInputElement e) => (e as Visual)?.IsVisible ?? true;
private static bool IsVisibleAndEnabled(IInputElement e) => IsVisible(e) && e.IsEnabled;
private static bool IsVisibleAndEnabled(IInputElement e) => IsVisible(e) && e.IsEffectivelyEnabled;
}
}

15
tests/Avalonia.Base.UnitTests/Input/KeyboardDeviceTests.cs

@ -1,6 +1,4 @@
using System;
using System.Windows.Input;
using Avalonia.Controls;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Input.Raw;
using Avalonia.UnitTests;
@ -112,7 +110,7 @@ namespace Avalonia.Base.UnitTests.Input
button.KeyBindings.Add(new KeyBinding
{
Gesture = new KeyGesture(Key.O, KeyModifiers.Control),
Command = new DelegateCommand(() =>
Command = new Utilities.DelegateCommand(() =>
{
button.KeyBindings.Clear();
++raised;
@ -134,15 +132,6 @@ namespace Avalonia.Base.UnitTests.Input
Assert.Equal(1, raised);
}
private class DelegateCommand : ICommand
{
private readonly Action _action;
public DelegateCommand(Action action) => _action = action;
public event EventHandler CanExecuteChanged { add { } remove { } }
public bool CanExecute(object parameter) => true;
public void Execute(object parameter) => _action();
}
[Fact]
public void Control_Focus_Should_Be_Set_Before_FocusedElement_Raises_PropertyChanged()
{

38
tests/Avalonia.Base.UnitTests/Input/KeyboardNavigationTests_Tab.cs

@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using Avalonia.Controls;
using Avalonia.Input;
@ -1273,5 +1274,42 @@ namespace Avalonia.Base.UnitTests.Input
Assert.True(button.IsFocused);
}
[Fact]
public void Next_Skip_Button_When_Command_CanExecute_Is_False()
{
Button current;
Button expected;
bool executed = false;
var top = new StackPanel
{
[KeyboardNavigation.TabNavigationProperty] = KeyboardNavigationMode.Cycle,
Children =
{
new StackPanel
{
Children =
{
(current = new Button { Name = "Button1" }),
new Button
{
Name = "Button2",
Command = new Utilities.DelegateCommand(()=>executed = true,
_ => false),
},
(expected = new Button { Name = "Button3" }),
}
}
}
};
var result = KeyboardNavigationHandler.GetNext(current, NavigationDirection.Next) as Button;
Assert.Equal(expected.Name, result?.Name);
Assert.False(executed);
}
}
}

19
tests/Avalonia.Base.UnitTests/Utilities/DelegateCommand.cs

@ -0,0 +1,19 @@
using System;
using System.Windows.Input;
namespace Avalonia.Base.UnitTests.Utilities;
internal class DelegateCommand : ICommand
{
private readonly Action _action;
private readonly Func<object, bool> _canExecute;
public DelegateCommand(Action action, Func<object, bool> canExecute = default)
{
_action = action;
_canExecute = canExecute ?? new(_ => true);
}
public event EventHandler CanExecuteChanged { add { } remove { } }
public bool CanExecute(object parameter) => _canExecute(parameter);
public void Execute(object parameter) => _action();
}
Loading…
Cancel
Save