diff --git a/src/Avalonia.Controls/ListBox.cs b/src/Avalonia.Controls/ListBox.cs
index 80b5259a53..86118d7b00 100644
--- a/src/Avalonia.Controls/ListBox.cs
+++ b/src/Avalonia.Controls/ListBox.cs
@@ -139,7 +139,8 @@ namespace Avalonia.Controls
e.Source,
true,
e.KeyModifiers.HasAllFlags(KeyModifiers.Shift),
- e.KeyModifiers.HasAllFlags(KeyModifiers.Control));
+ e.KeyModifiers.HasAllFlags(KeyModifiers.Control),
+ fromFocus: true);
}
}
diff --git a/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs b/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs
index ea20247b4b..e03b02a479 100644
--- a/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs
+++ b/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs
@@ -586,6 +586,14 @@ namespace Avalonia.Controls.Primitives
Selection.SelectAll();
e.Handled = true;
}
+ else if (e.Key == Key.Space || e.Key == Key.Enter)
+ {
+ e.Handled = UpdateSelectionFromEventSource(
+ e.Source,
+ true,
+ e.KeyModifiers.HasFlag(KeyModifiers.Shift),
+ e.KeyModifiers.HasFlag(KeyModifiers.Control));
+ }
}
}
@@ -662,12 +670,14 @@ namespace Avalonia.Controls.Primitives
/// Whether the range modifier is enabled (i.e. shift key).
/// Whether the toggle modifier is enabled (i.e. ctrl key).
/// Whether the event is a right-click.
+ /// Wheter the event is a focus event
protected void UpdateSelection(
int index,
bool select = true,
bool rangeModifier = false,
bool toggleModifier = false,
- bool rightButton = false)
+ bool rightButton = false,
+ bool fromFocus = false)
{
if (index < 0 || index >= ItemCount)
{
@@ -696,22 +706,25 @@ namespace Avalonia.Controls.Primitives
Selection.Clear();
Selection.SelectRange(Selection.AnchorIndex, index);
}
- else if (multi && toggle)
+ else if (!fromFocus && toggle)
{
- if (Selection.IsSelected(index) == true)
+ if (multi)
{
- Selection.Deselect(index);
+ if (Selection.IsSelected(index) == true)
+ {
+ Selection.Deselect(index);
+ }
+ else
+ {
+ Selection.Select(index);
+ }
}
else
{
- Selection.Select(index);
+ SelectedIndex = (SelectedIndex == index) ? -1 : index;
}
}
- else if (toggle)
- {
- SelectedIndex = (SelectedIndex == index) ? -1 : index;
- }
- else
+ else if (!toggle)
{
using var operation = Selection.BatchUpdate();
Selection.Clear();
@@ -735,18 +748,20 @@ namespace Avalonia.Controls.Primitives
/// Whether the range modifier is enabled (i.e. shift key).
/// Whether the toggle modifier is enabled (i.e. ctrl key).
/// Whether the event is a right-click.
+ /// Wheter the event is a focus event
protected void UpdateSelection(
IControl container,
bool select = true,
bool rangeModifier = false,
bool toggleModifier = false,
- bool rightButton = false)
+ bool rightButton = false,
+ bool fromFocus = false)
{
var index = ItemContainerGenerator?.IndexFromContainer(container) ?? -1;
if (index != -1)
{
- UpdateSelection(index, select, rangeModifier, toggleModifier, rightButton);
+ UpdateSelection(index, select, rangeModifier, toggleModifier, rightButton, fromFocus);
}
}
@@ -759,6 +774,7 @@ namespace Avalonia.Controls.Primitives
/// Whether the range modifier is enabled (i.e. shift key).
/// Whether the toggle modifier is enabled (i.e. ctrl key).
/// Whether the event is a right-click.
+ /// Wheter the event is a focus event
///
/// True if the event originated from a container that belongs to the control; otherwise
/// false.
@@ -768,13 +784,14 @@ namespace Avalonia.Controls.Primitives
bool select = true,
bool rangeModifier = false,
bool toggleModifier = false,
- bool rightButton = false)
+ bool rightButton = false,
+ bool fromFocus = false)
{
var container = GetContainerFromEventSource(eventSource);
if (container != null)
{
- UpdateSelection(container, select, rangeModifier, toggleModifier, rightButton);
+ UpdateSelection(container, select, rangeModifier, toggleModifier, rightButton, fromFocus);
return true;
}
diff --git a/tests/Avalonia.Controls.UnitTests/ListBoxTests_Multiple.cs b/tests/Avalonia.Controls.UnitTests/ListBoxTests_Multiple.cs
index 7c7cdd08db..556959effb 100644
--- a/tests/Avalonia.Controls.UnitTests/ListBoxTests_Multiple.cs
+++ b/tests/Avalonia.Controls.UnitTests/ListBoxTests_Multiple.cs
@@ -36,7 +36,7 @@ namespace Avalonia.Controls.UnitTests
}
[Fact]
- public void Focusing_Item_With_Ctrl_And_Arrow_Key_Should_Add_To_Selection()
+ public void Focusing_Item_With_Ctrl_And_Arrow_Key_Should_Not_Add_To_Selection()
{
var target = new ListBox
{
@@ -56,11 +56,11 @@ namespace Avalonia.Controls.UnitTests
KeyModifiers = KeyModifiers.Control
});
- Assert.Equal(new[] { "Foo", "Bar" }, target.SelectedItems);
+ Assert.Equal(new[] { "Foo" }, target.SelectedItems);
}
[Fact]
- public void Focusing_Selected_Item_With_Ctrl_And_Arrow_Key_Should_Remove_From_Selection()
+ public void Focusing_Selected_Item_With_Ctrl_And_Arrow_Key_Should_Not_Remove_From_Selection()
{
var target = new ListBox
{
@@ -81,7 +81,7 @@ namespace Avalonia.Controls.UnitTests
KeyModifiers = KeyModifiers.Control
});
- Assert.Equal(new[] { "Bar" }, target.SelectedItems);
+ Assert.Equal(new[] { "Foo", "Bar" }, target.SelectedItems);
}
private Control CreateListBoxTemplate(ITemplatedControl parent, INameScope scope)
diff --git a/tests/Avalonia.Controls.UnitTests/ListBoxTests_Single.cs b/tests/Avalonia.Controls.UnitTests/ListBoxTests_Single.cs
index bf516748cc..726a39ac46 100644
--- a/tests/Avalonia.Controls.UnitTests/ListBoxTests_Single.cs
+++ b/tests/Avalonia.Controls.UnitTests/ListBoxTests_Single.cs
@@ -59,6 +59,58 @@ namespace Avalonia.Controls.UnitTests
Assert.Equal(0, target.SelectedIndex);
}
+ [Fact]
+ public void Focusing_Item_With_Arrow_Key_And_Ctrl_Pressed_Should_Not_Select_It()
+ {
+ var target = new ListBox
+ {
+ Template = new FuncControlTemplate(CreateListBoxTemplate),
+ Items = new[] { "Foo", "Bar", "Baz " },
+ };
+
+ ApplyTemplate(target);
+
+ target.Presenter.Panel.Children[0].RaiseEvent(new GotFocusEventArgs
+ {
+ RoutedEvent = InputElement.GotFocusEvent,
+ NavigationMethod = NavigationMethod.Directional,
+ KeyModifiers = KeyModifiers.Control
+ });
+
+ Assert.Equal(-1, target.SelectedIndex);
+ }
+
+ [Fact]
+ public void Pressing_Space_On_Focused_Item_With_Ctrl_Pressed_Should_Select_It()
+ {
+ using (UnitTestApplication.Start())
+ {
+ var target = new ListBox
+ {
+ Template = new FuncControlTemplate(CreateListBoxTemplate),
+ Items = new[] { "Foo", "Bar", "Baz " },
+ };
+ AvaloniaLocator.CurrentMutable.Bind().ToConstant(new Mock().Object);
+ ApplyTemplate(target);
+
+ target.Presenter.Panel.Children[0].RaiseEvent(new GotFocusEventArgs
+ {
+ RoutedEvent = InputElement.GotFocusEvent,
+ NavigationMethod = NavigationMethod.Directional,
+ KeyModifiers = KeyModifiers.Control
+ });
+
+ target.Presenter.Panel.Children[0].RaiseEvent(new KeyEventArgs
+ {
+ RoutedEvent = InputElement.KeyDownEvent,
+ Key = Key.Space,
+ KeyModifiers = KeyModifiers.Control
+ });
+
+ Assert.Equal(0, target.SelectedIndex);
+ }
+ }
+
[Fact]
public void Clicking_Item_Should_Select_It()
{