Skip to content

Commit 74827b2

Browse files
[iOS] - Resolved Proper Rendering of Dynamic Header/Footer Updates in CV2 (dotnet#28641)
* Fixed-Header-Footer-Issues-In-CV2 * Modified-Test * Android-Specific Test Restriction * Modified-fix * Added-Comment
1 parent 1d8d351 commit 74827b2

File tree

6 files changed

+490
-2
lines changed

6 files changed

+490
-2
lines changed

src/Controls/src/Core/Handlers/Items2/CollectionViewHandler2.iOS.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ public CollectionViewHandler2(PropertyMapper mapper = null) : base(mapper ?? Map
5656
[StructuredItemsView.FooterTemplateProperty.PropertyName] = MapFooterTemplate,
5757
[StructuredItemsView.HeaderProperty.PropertyName] = MapHeaderTemplate,
5858
[StructuredItemsView.FooterProperty.PropertyName] = MapFooterTemplate,
59+
[GroupableItemsView.GroupHeaderTemplateProperty.PropertyName] = MapHeaderTemplate,
60+
[GroupableItemsView.GroupFooterTemplateProperty.PropertyName] = MapFooterTemplate,
5961
};
6062
}
6163

src/Controls/src/Core/Handlers/Items2/iOS/GroupableItemsViewController2.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,9 @@ void UpdateTemplatedSupplementaryView(TemplatedCell2 cell, NSString elementKind,
127127

128128
var bindingContext = ItemsSource.Group(indexPath);
129129

130+
cell.isHeaderOrFooterChanged = true;
130131
cell.Bind(template, bindingContext, ItemsView);
132+
cell.isHeaderOrFooterChanged = false;
131133

132134
// if (cell is ItemsViewCell2)
133135
// {

src/Controls/src/Core/Handlers/Items2/iOS/StructuredItemsViewController2.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ void UpdateDefaultSupplementaryView(DefaultCell2 cell, NSString elementKind)
106106
void UpdateTemplatedSupplementaryView(TemplatedCell2 cell, NSString elementKind)
107107
{
108108
bool isHeader = elementKind == UICollectionElementKindSectionKey.Header;
109+
cell.isHeaderOrFooterChanged = true;
109110

110111
if (isHeader)
111112
{
@@ -131,6 +132,8 @@ void UpdateTemplatedSupplementaryView(TemplatedCell2 cell, NSString elementKind)
131132
}
132133
cell.Tag = FooterTag;
133134
}
135+
136+
cell.isHeaderOrFooterChanged = false;
134137
}
135138

136139
string DetermineViewReuseId(DataTemplate template, object item)

src/Controls/src/Core/Handlers/Items2/iOS/TemplatedCell2.cs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ public event EventHandler<LayoutAttributesChangedEventArgs2> LayoutAttributesCha
4242

4343
internal bool MeasureInvalidated => _measureInvalidated;
4444

45+
// Flags changes confined to the header/footer, preventing unnecessary recycling and revalidation of templated cells.
46+
internal bool isHeaderOrFooterChanged = false;
47+
4548
public DataTemplate CurrentTemplate
4649
{
4750
get => _currentTemplate is not null && _currentTemplate.TryGetTarget(out var target) ? target : null;
@@ -144,8 +147,16 @@ public override void PrepareForReuse()
144147

145148
public void Bind(DataTemplate template, object bindingContext, ItemsView itemsView)
146149
{
147-
var virtualView = PlatformHandler?.VirtualView as View ??
148-
template.CreateContent(bindingContext, itemsView) as View;
150+
View virtualView = null;
151+
if (CurrentTemplate != template)
152+
{
153+
CurrentTemplate = template;
154+
virtualView = template.CreateContent(bindingContext, itemsView) as View;
155+
}
156+
else if (PlatformHandler?.VirtualView is View existingView)
157+
{
158+
virtualView = existingView;
159+
}
149160

150161
BindVirtualView(virtualView, bindingContext, itemsView, false);
151162
}
@@ -157,6 +168,16 @@ public void Bind(View virtualView, ItemsView itemsView)
157168

158169
void BindVirtualView(View virtualView, object bindingContext, ItemsView itemsView, bool needsContainer)
159170
{
171+
var oldElement = PlatformHandler?.VirtualView as View;
172+
173+
if (oldElement is not null && oldElement != virtualView && isHeaderOrFooterChanged)
174+
{
175+
oldElement.BindingContext = null;
176+
itemsView.RemoveLogicalChild(oldElement);
177+
PlatformHandler = null;
178+
PlatformView?.RemoveFromSuperview();
179+
}
180+
160181
if (PlatformHandler is null && virtualView is not null)
161182
{
162183
var mauiContext = itemsView.FindMauiContext()!;

0 commit comments

Comments
 (0)