Browse Source

Merge pull request #9144 from emmauss/listbox_control_selection

Prevent SelectingItemsControl's selection from being updated on focus when toggle is enabled
pull/9284/head
Max Katz 4 years ago
committed by GitHub
parent
commit
84c3fbea21
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      src/Avalonia.Controls/ListBox.cs
  2. 45
      src/Avalonia.Controls/Primitives/SelectingItemsControl.cs
  3. 8
      tests/Avalonia.Controls.UnitTests/ListBoxTests_Multiple.cs
  4. 52
      tests/Avalonia.Controls.UnitTests/ListBoxTests_Single.cs

3
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);
}
}

45
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
/// <param name="rangeModifier">Whether the range modifier is enabled (i.e. shift key).</param>
/// <param name="toggleModifier">Whether the toggle modifier is enabled (i.e. ctrl key).</param>
/// <param name="rightButton">Whether the event is a right-click.</param>
/// <param name="fromFocus">Wheter the event is a focus event</param>
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
/// <param name="rangeModifier">Whether the range modifier is enabled (i.e. shift key).</param>
/// <param name="toggleModifier">Whether the toggle modifier is enabled (i.e. ctrl key).</param>
/// <param name="rightButton">Whether the event is a right-click.</param>
/// <param name="fromFocus">Wheter the event is a focus event</param>
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
/// <param name="rangeModifier">Whether the range modifier is enabled (i.e. shift key).</param>
/// <param name="toggleModifier">Whether the toggle modifier is enabled (i.e. ctrl key).</param>
/// <param name="rightButton">Whether the event is a right-click.</param>
/// <param name="fromFocus">Wheter the event is a focus event</param>
/// <returns>
/// 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;
}

8
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)

52
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<PlatformHotkeyConfiguration>().ToConstant(new Mock<PlatformHotkeyConfiguration>().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()
{

Loading…
Cancel
Save