Browse Source

Merge pull request #11783 from AvaloniaUI/fixes/11679-listbox-losing-selection-on-container-focus-lost

Fix ListBox losing selection on container focus lost
pull/11798/head
Max Katz 3 years ago
committed by GitHub
parent
commit
1ebdced2a5
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 11
      src/Avalonia.Controls/Primitives/SelectingItemsControl.cs
  2. 61
      tests/Avalonia.Controls.UnitTests/VirtualizingStackPanelTests.cs

11
src/Avalonia.Controls/Primitives/SelectingItemsControl.cs

@ -533,7 +533,16 @@ namespace Avalonia.Controls.Primitives
protected internal override void ClearContainerForItemOverride(Control element)
{
base.ClearContainerForItemOverride(element);
element.ClearValue(IsSelectedProperty);
try
{
_ignoreContainerSelectionChanged = true;
element.ClearValue(IsSelectedProperty);
}
finally
{
_ignoreContainerSelectionChanged = false;
}
}
/// <inheritdoc/>

61
tests/Avalonia.Controls.UnitTests/VirtualizingStackPanelTests.cs

@ -367,6 +367,38 @@ namespace Avalonia.Controls.UnitTests
Assert.False(originalFocused.IsVisible);
}
[Fact]
public void Focused_Element_Losing_Focus_Does_Not_Reset_Selection()
{
using var app = App();
var (target, scroll, listBox) = CreateTarget<ListBox>(
styles: new[]
{
new Style(x => x.OfType<ListBoxItem>())
{
Setters =
{
new Setter(ListBoxItem.TemplateProperty, ListBoxItemTemplate()),
}
}
});
listBox.SelectedIndex = 0;
var selectedContainer = target.GetRealizedElements().First()!;
selectedContainer.Focusable = true;
selectedContainer.Focus();
scroll.Offset = new Vector(0, 500);
Layout(target);
var newFocused = target.GetRealizedElements().First()!;
newFocused.Focusable = true;
newFocused.Focus();
Assert.Equal(0, listBox.SelectedIndex);
}
[Fact]
public void Removing_Range_When_Scrolled_To_End_Updates_Viewport()
{
@ -776,7 +808,19 @@ namespace Avalonia.Controls.UnitTests
Optional<IDataTemplate?> itemTemplate = default,
IEnumerable<Style>? styles = null)
{
var (target, scroll, itemsControl) = CreateUnrootedTarget<ItemsControl>(items, itemTemplate);
return CreateTarget<ItemsControl>(
items: items,
itemTemplate: itemTemplate,
styles: styles);
}
private static (VirtualizingStackPanel, ScrollViewer, T) CreateTarget<T>(
IEnumerable<object>? items = null,
Optional<IDataTemplate?> itemTemplate = default,
IEnumerable<Style>? styles = null)
where T : ItemsControl, new()
{
var (target, scroll, itemsControl) = CreateUnrootedTarget<T>(items, itemTemplate);
var root = CreateRoot(itemsControl, styles);
root.LayoutManager.ExecuteInitialLayoutPass();
@ -808,7 +852,7 @@ namespace Avalonia.Controls.UnitTests
var itemsControl = new T
{
ItemsSource = items,
Template = new FuncControlTemplate<ItemsControl>((_, ns) => scroll.RegisterInNameScope(ns)),
Template = new FuncControlTemplate<T>((_, ns) => scroll.RegisterInNameScope(ns)),
ItemsPanel = new FuncTemplate<Panel?>(() => target),
ItemTemplate = itemTemplate.GetValueOrDefault(DefaultItemTemplate()),
};
@ -838,12 +882,23 @@ namespace Avalonia.Controls.UnitTests
root?.LayoutManager.ExecuteLayoutPass();
}
private static IControlTemplate ListBoxItemTemplate()
{
return new FuncControlTemplate<ListBoxItem>((x, ns) =>
new ContentPresenter
{
Name = "PART_ContentPresenter",
Width = 100,
Height = 10,
}.RegisterInNameScope(ns));
}
private static IControlTemplate ScrollViewerTemplate()
{
return new FuncControlTemplate<ScrollViewer>((x, ns) =>
new ScrollContentPresenter
{
Name = "PART_ContentPresenter",
Name = "PART_ScrollContentPresenter",
}.RegisterInNameScope(ns));
}

Loading…
Cancel
Save