Skip to content

Commit

Permalink
fix(ListViewBase): Item container indices not updated on insert/remove
Browse files Browse the repository at this point in the history
  • Loading branch information
MartinZikmund committed Sep 28, 2020
1 parent 7187982 commit ebdca5d
Showing 1 changed file with 41 additions and 3 deletions.
44 changes: 41 additions & 3 deletions src/Uno.UI/UI/Xaml/Controls/ListViewBase/ListViewBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ public partial class ListViewBase : Selector
/// </summary>
private bool _isIncrementalLoadingInFlight;

private readonly Dictionary<DependencyObject, object> _containersForIndexRepair = new Dictionary<DependencyObject, object>();

protected internal ListViewBase()
{
Initialize();
Expand All @@ -58,7 +60,7 @@ protected internal ListViewBase()
SelectedItems = selectedItems;
}

public event TypedEventHandler<ListViewBase, ContainerContentChangingEventArgs> ContainerContentChanging;
public event TypedEventHandler<ListViewBase, ContainerContentChangingEventArgs> ContainerContentChanging;

protected override Size ArrangeOverride(Size finalSize)
{
Expand Down Expand Up @@ -173,7 +175,8 @@ internal override void ChangeSelectedItem(object item, bool oldIsSelected, bool
{
SelectedIndex = -1;
}
} else
}
else
{
SelectedIndex = index;
}
Expand Down Expand Up @@ -461,7 +464,11 @@ internal override void OnItemsSourceSingleCollectionChanged(object sender, Notif
{
this.Log().Debug($"Inserting {args.NewItems.Count} items starting at {args.NewStartingIndex}");
}

SaveContainersForIndexRepair(args.NewStartingIndex, args.NewItems.Count);
AddItems(args.NewStartingIndex, args.NewItems.Count, section);
RepairIndices();

break;
case NotifyCollectionChangedAction.Remove:
if (AreEmptyGroupsHidden && (sender as IEnumerable).None())
Expand All @@ -475,14 +482,20 @@ internal override void OnItemsSourceSingleCollectionChanged(object sender, Notif
{
this.Log().Debug($"Deleting {args.OldItems.Count} items starting at {args.OldStartingIndex}");
}

SaveContainersForIndexRepair(args.OldStartingIndex, -args.OldItems.Count);
RemoveItems(args.OldStartingIndex, args.OldItems.Count, section);
RepairIndices();

break;
case NotifyCollectionChangedAction.Replace:
if (this.Log().IsEnabled(Microsoft.Extensions.Logging.LogLevel.Debug))
{
this.Log().Debug($"Replacing {args.NewItems.Count} items starting at {args.NewStartingIndex}");
}

ReplaceItems(args.NewStartingIndex, args.NewItems.Count, section);

break;
case NotifyCollectionChangedAction.Move:
// TODO PBI #19974: Fully implement NotifyCollectionChangedActions and map them to the appropriate calls
Expand All @@ -505,6 +518,28 @@ void completeRefresh()
}
}

private void SaveContainersForIndexRepair(int startingIndex, int indexChange)
{
_containersForIndexRepair.Clear();
foreach (var container in MaterializedContainers)
{
var currentIndex = (int)container.GetValue(ItemsControl.IndexForItemContainerProperty);
if (currentIndex >= startingIndex)
{
_containersForIndexRepair.Add(container, currentIndex + indexChange);
}
}
}

private void RepairIndices()
{
foreach(var containerPair in _containersForIndexRepair)
{
containerPair.Key.SetValue(ItemsControl.IndexForItemContainerProperty, containerPair.Value);
}
_containersForIndexRepair.Clear();
}

internal override void OnItemsSourceGroupsChanged(object sender, NotifyCollectionChangedEventArgs args)
{
if (RefreshOnCollectionChanged)
Expand Down Expand Up @@ -596,6 +631,9 @@ internal override void OnGroupPropertyChanged(ICollectionViewGroup group, int gr

protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
{
// Index will be repaired by virtue of ItemsControl.
_containersForIndexRepair.Remove(element);

base.PrepareContainerForItemOverride(element, item);

if (element is SelectorItem selectorItem)
Expand All @@ -607,7 +645,7 @@ protected override void PrepareContainerForItemOverride(DependencyObject element
internal override void ContainerPreparedForItem(object item, SelectorItem itemContainer, int itemIndex)
{
base.ContainerPreparedForItem(item, itemContainer, itemIndex);

ContainerContentChanging?.Invoke(this, new ContainerContentChangingEventArgs(item, itemContainer, itemIndex));
}

Expand Down

0 comments on commit ebdca5d

Please sign in to comment.