Skip to content

Commit fb711d4

Browse files
CollectionView Header/Footer/EmptyView issues when adding/removing items. (#24830)
* Fixed: 11896 - CollectionView Header/Footer/EmptyView issues when adding/removing items * updated Items/ItemsViewHandler.Android.cs * Added testcases. * Added ios fix. * updated Issue11896.cs * updated Issue11896.cs * Added output images. * ios images updated.
1 parent 9a9a4bd commit fb711d4

File tree

10 files changed

+176
-18
lines changed

10 files changed

+176
-18
lines changed

src/Controls/src/Core/Handlers/Items/Android/Adapters/AdapterNotifier.cs

-16
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,6 @@ public void NotifyItemInserted(IItemsViewSource source, int startIndex)
2929
if (IsValidAdapter())
3030
{
3131
_adapter.NotifyItemInserted(startIndex);
32-
33-
var changedCount = _adapter.ItemCount - startIndex;
34-
_adapter.NotifyItemRangeChanged(startIndex, changedCount);
3532
}
3633
}
3734

@@ -40,10 +37,6 @@ public void NotifyItemMoved(IItemsViewSource source, int fromPosition, int toPos
4037
if (IsValidAdapter())
4138
{
4239
_adapter.NotifyItemMoved(fromPosition, toPosition);
43-
44-
var minPosition = System.Math.Min(fromPosition, toPosition);
45-
var changedCount = _adapter.ItemCount - minPosition;
46-
_adapter.NotifyItemRangeChanged(minPosition, changedCount);
4740
}
4841
}
4942

@@ -58,9 +51,6 @@ public void NotifyItemRangeInserted(IItemsViewSource source, int startIndex, int
5851
if (IsValidAdapter())
5952
{
6053
_adapter.NotifyItemRangeInserted(startIndex, count);
61-
62-
var changedCount = _adapter.ItemCount - startIndex;
63-
_adapter.NotifyItemRangeChanged(startIndex, changedCount);
6454
}
6555
}
6656

@@ -69,9 +59,6 @@ public void NotifyItemRangeRemoved(IItemsViewSource source, int startIndex, int
6959
if (IsValidAdapter())
7060
{
7161
_adapter.NotifyItemRangeRemoved(startIndex, count);
72-
73-
var changedCount = _adapter.ItemCount - startIndex;
74-
_adapter.NotifyItemRangeChanged(startIndex, changedCount);
7562
}
7663
}
7764

@@ -80,9 +67,6 @@ public void NotifyItemRemoved(IItemsViewSource source, int startIndex)
8067
if (IsValidAdapter())
8168
{
8269
_adapter.NotifyItemRemoved(startIndex);
83-
84-
var changedCount = _adapter.ItemCount - startIndex;
85-
_adapter.NotifyItemRangeChanged(startIndex, changedCount);
8670
}
8771
}
8872

src/Controls/src/Core/Handlers/Items/Android/MauiRecyclerView.cs

+3-1
Original file line numberDiff line numberDiff line change
@@ -567,11 +567,12 @@ internal void UpdateEmptyViewVisibility()
567567
itemCount++;
568568
}
569569

570-
var showEmptyView = ItemsView?.EmptyView != null && ItemsViewAdapter.ItemCount == itemCount;
570+
var showEmptyView = (ItemsView?.EmptyView is not null || ItemsView?.EmptyViewTemplate is not null) && ItemsViewAdapter.ItemCount == itemCount;
571571

572572
var currentAdapter = GetAdapter();
573573
if (showEmptyView && currentAdapter != _emptyViewAdapter)
574574
{
575+
GetRecycledViewPool().Clear();
575576
SwapAdapter(_emptyViewAdapter, true);
576577

577578
// TODO hartez 2018/10/24 17:34:36 If this works, cache this layout manager as _emptyLayoutManager
@@ -580,6 +581,7 @@ internal void UpdateEmptyViewVisibility()
580581
}
581582
else if (!showEmptyView && currentAdapter != ItemsViewAdapter)
582583
{
584+
GetRecycledViewPool().Clear();
583585
SwapAdapter(ItemsViewAdapter, true);
584586
UpdateLayoutManager();
585587
}

src/Controls/src/Core/Handlers/Items/iOS/ItemsViewController.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -567,7 +567,7 @@ protected virtual void HandleFormsElementMeasureInvalidated(VisualElement formsE
567567
internal void UpdateView(object view, DataTemplate viewTemplate, ref UIView uiView, ref VisualElement formsElement)
568568
{
569569
// Is view set on the ItemsView?
570-
if (view == null)
570+
if (view is null && viewTemplate is null)
571571
{
572572
if (formsElement != null)
573573
{
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
3+
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
4+
x:Class="Maui.Controls.Sample.Issues.Issue11896"
5+
xmlns:local="clr-namespace:Maui.Controls.Sample.Issues"
6+
x:Name="ThisMainPage"
7+
Title="Main Page">
8+
9+
<Grid RowDefinitions="Auto,*">
10+
11+
<HorizontalStackLayout
12+
Grid.Row="0"
13+
Padding="20"
14+
HorizontalOptions="Center"
15+
Spacing="20">
16+
<Button Command="{Binding AddCommand}" Text="Add item" AutomationId="AddButton" />
17+
<Button Command="{Binding RemoveCommand}" Text="Remove item" AutomationId="RemoveButton" />
18+
</HorizontalStackLayout>
19+
20+
<CollectionView Grid.Row="1" ItemsSource="{Binding ItemList}">
21+
22+
<CollectionView.HeaderTemplate>
23+
<DataTemplate>
24+
<Label
25+
Padding="10"
26+
FontAttributes="Bold"
27+
FontSize="Large"
28+
Text="Cities" />
29+
</DataTemplate>
30+
</CollectionView.HeaderTemplate>
31+
32+
<CollectionView.ItemTemplate>
33+
<DataTemplate>
34+
<Label Padding="20,5,5,5" Text="{Binding .}" />
35+
</DataTemplate>
36+
</CollectionView.ItemTemplate>
37+
38+
<CollectionView.EmptyViewTemplate>
39+
<DataTemplate>
40+
<Label Padding="20,5,5,5" Text="Empty" />
41+
</DataTemplate>
42+
</CollectionView.EmptyViewTemplate>
43+
44+
<CollectionView.FooterTemplate>
45+
<DataTemplate>
46+
<Label
47+
Padding="10"
48+
FontAttributes="Bold"
49+
FontSize="Large"
50+
Text="Hello world !!!" />
51+
</DataTemplate>
52+
</CollectionView.FooterTemplate>
53+
54+
</CollectionView>
55+
56+
</Grid>
57+
</ContentPage>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Collections.ObjectModel;
4+
using System.ComponentModel;
5+
using System.Runtime.CompilerServices;
6+
using System.Windows.Input;
7+
using System.Collections.Specialized;
8+
9+
10+
namespace Maui.Controls.Sample.Issues
11+
{
12+
[XamlCompilation(XamlCompilationOptions.Compile)]
13+
[Issue(IssueTracker.Github, 11896, "CollectionView Header/Footer/EmptyView issues when adding/removing items", PlatformAffected.Android)]
14+
public partial class Issue11896
15+
{
16+
public Issue11896()
17+
{
18+
InitializeComponent();
19+
BindingContext = new Issue11896ViewModel();
20+
}
21+
}
22+
internal class Issue11896ViewModel
23+
{
24+
// Define a static list of cities to add to the collection
25+
private List<string> _staticCities = new()
26+
{
27+
"Paris",
28+
"New York",
29+
"Tokyo",
30+
"Berlin",
31+
"Madrid",
32+
"London"
33+
};
34+
35+
private int _currentIndex = 0;
36+
37+
public ObservableCollection<string> ItemList { get; set; }
38+
39+
public ICommand AddCommand => new Command(Add);
40+
public ICommand RemoveCommand => new Command(Remove);
41+
42+
public Issue11896ViewModel()
43+
{
44+
// Initialize the ItemList
45+
ItemList = new ObservableCollection<string>();
46+
}
47+
48+
private void Add()
49+
{
50+
// Add the next city from the static list
51+
if (_currentIndex < _staticCities.Count)
52+
{
53+
ItemList.Add(_staticCities[_currentIndex]);
54+
_currentIndex++;
55+
}
56+
else
57+
{
58+
// Optionally reset the index or handle the end of the list as needed
59+
_currentIndex = 0; // Resetting to allow cycling through the list again
60+
}
61+
}
62+
63+
private void Remove()
64+
{
65+
// Remove the last item in the list if any exist
66+
if (ItemList.Count > 0)
67+
{
68+
ItemList.RemoveAt(ItemList.Count - 1);
69+
// Decrement the index to ensure the correct city is added next time
70+
_currentIndex = Math.Max(0, _currentIndex - 1);
71+
}
72+
}
73+
}
74+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#if !MACCATALYST && !WINDOWS
2+
using NUnit.Framework;
3+
using UITest.Appium;
4+
using UITest.Core;
5+
6+
namespace Microsoft.Maui.TestCases.Tests.Issues
7+
{
8+
internal class Issue11896 : _IssuesUITest
9+
{
10+
public Issue11896(TestDevice device) : base(device) { }
11+
12+
public override string Issue => "CollectionView Header/Footer/EmptyView issues when adding/removing items";
13+
14+
[Test]
15+
16+
[Category(UITestCategories.CollectionView)]
17+
public void CollectionviewFooterHideswhenDynamicallyAddorRemoveItems()
18+
{
19+
App.WaitForElement("AddButton");
20+
App.Tap("AddButton");
21+
App.Tap("AddButton");
22+
App.Tap("AddButton");
23+
// Here we check for Footer proper visibility with proper alignment in view.
24+
VerifyScreenshot();
25+
}
26+
27+
[Test]
28+
[Category(UITestCategories.CollectionView)]
29+
public void CollectionViewHeaderBlankWhenLastItemRemoved()
30+
{
31+
App.WaitForElement("AddButton");
32+
App.Tap("RemoveButton");
33+
App.Tap("RemoveButton");
34+
App.Tap("RemoveButton");
35+
App.Tap("AddButton");
36+
// Here we check for Header and Footer proper visibility with proper alignment in view.
37+
VerifyScreenshot();
38+
}
39+
}
40+
}
41+
#endif

0 commit comments

Comments
 (0)