Skip to content

Commit 21ba331

Browse files
committed
Resolve #36. Fix ScrollView clear collection issue.
1 parent 978fd29 commit 21ba331

File tree

4 files changed

+94
-17
lines changed

4 files changed

+94
-17
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using UnityMvvmToolkit.Core.Interfaces;
4+
5+
namespace UnityMvvmToolkit.Common
6+
{
7+
public sealed class BindableElementData : IDisposable
8+
{
9+
private readonly List<IBindableElement> _bindableElements;
10+
11+
public BindableElementData(List<IBindableElement> bindableElements)
12+
{
13+
_bindableElements = bindableElements;
14+
}
15+
16+
public IBindingContext BindingContext { get; set; }
17+
public IReadOnlyList<IBindableElement> BindableElements => _bindableElements;
18+
19+
public void Dispose()
20+
{
21+
_bindableElements.Clear();
22+
BindingContext = default;
23+
}
24+
}
25+
}

src/UnityMvvmToolkit.UnityPackage/Assets/Plugins/UnityMvvmToolkit/Runtime/Common/BindableElementData.cs.meta

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/UnityMvvmToolkit.UnityPackage/Assets/Plugins/UnityMvvmToolkit/Runtime/UITK/BindableUIElements/BindableScrollView.T.cs

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ public abstract partial class BindableScrollView<TItemBindingContext> : ScrollVi
2121
private VisualTreeAsset _itemTemplate;
2222

2323
private PropertyBindingData _itemsSourceBindingData;
24-
private IReadOnlyProperty<ObservableCollection<TItemBindingContext>> _itemsSource;
24+
private ObservableCollection<TItemBindingContext> _itemsSource;
25+
private IReadOnlyProperty<ObservableCollection<TItemBindingContext>> _itemsSourceProperty;
2526

2627
private IObjectProvider _objectProvider;
2728

@@ -44,7 +45,7 @@ public virtual void Dispose()
4445
}
4546
else
4647
{
47-
ClearItems(_itemsSource.Value);
48+
ClearItems(_itemsSource);
4849
}
4950

5051
_itemAssetsPool.Dispose();
@@ -62,29 +63,32 @@ public virtual void SetBindingContext(IBindingContext context, IObjectProvider o
6263

6364
_objectProvider = objectProvider;
6465

65-
_itemsSource = objectProvider
66+
_itemsSourceProperty = objectProvider
6667
.RentReadOnlyProperty<ObservableCollection<TItemBindingContext>>(context, _itemsSourceBindingData);
67-
_itemsSource.Value.CollectionChanged += OnItemsCollectionChanged;
68+
_itemsSource = _itemsSourceProperty.Value;
69+
_itemsSource.CollectionChanged += OnItemsCollectionChanged;
6870

69-
AddItems(_itemsSource.Value);
71+
AddItems(_itemsSource);
7072
}
7173

7274
public virtual void ResetBindingContext(IObjectProvider objectProvider)
7375
{
74-
if (_itemsSource is null)
76+
if (_itemsSourceProperty is null)
7577
{
7678
return;
7779
}
7880

79-
_itemsSource.Value.CollectionChanged -= OnItemsCollectionChanged;
81+
_itemsSource.CollectionChanged -= OnItemsCollectionChanged;
8082

81-
ClearItems(_itemsSource.Value);
83+
ClearItems(_itemsSource);
8284

83-
objectProvider.ReturnReadOnlyProperty(_itemsSource);
85+
objectProvider.ReturnReadOnlyProperty(_itemsSourceProperty);
8486

85-
_itemsSource = null;
8687
_itemTemplate = null;
8788
_objectProvider = null;
89+
90+
_itemsSource = null;
91+
_itemsSourceProperty = null;
8892
}
8993

9094
protected virtual VisualElement MakeItem(VisualTreeAsset itemTemplate)
@@ -125,6 +129,18 @@ protected virtual void OnItemsCollectionChanged(object sender, NotifyCollectionC
125129
RemoveItem((TItemBindingContext) oldItem);
126130
}
127131
}
132+
133+
if (e.Action == NotifyCollectionChangedAction.Reset)
134+
{
135+
if (_itemsSource.Count == 0)
136+
{
137+
ClearItems();
138+
}
139+
else
140+
{
141+
throw new InvalidOperationException("Action not supported.");
142+
}
143+
}
128144
}
129145

130146
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -173,6 +189,24 @@ private void ClearItems(IReadOnlyList<TItemBindingContext> items)
173189
}
174190
}
175191

192+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
193+
private void ClearItems()
194+
{
195+
foreach (var (_, item) in _itemAssets)
196+
{
197+
_itemsCount--;
198+
199+
if (_objectProvider is not null)
200+
{
201+
UnbindItem(item, _itemsCount, item.GetBindingContext<TItemBindingContext>(), _objectProvider);
202+
}
203+
204+
_itemAssetsPool.Release(item);
205+
}
206+
207+
_itemAssets.Clear();
208+
}
209+
176210
private VisualElement OnPoolInstantiateItem()
177211
{
178212
return MakeItem(_itemTemplate);

src/UnityMvvmToolkit.UnityPackage/Assets/Plugins/UnityMvvmToolkit/Runtime/UITK/Extensions/VisualElementExtensions.cs

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.Runtime.CompilerServices;
44
using JetBrains.Annotations;
55
using UnityEngine.UIElements;
6+
using UnityMvvmToolkit.Common;
67
using UnityMvvmToolkit.Common.Interfaces;
78
using UnityMvvmToolkit.Core.Interfaces;
89

@@ -14,7 +15,7 @@ public static partial class VisualElementExtensions
1415
public static VisualElement InstantiateBindableElement(this VisualTreeAsset visualTreeAsset)
1516
{
1617
var visualElement = visualTreeAsset.Instantiate();
17-
visualElement.userData = visualElement.GetBindableChilds();
18+
visualElement.userData = new BindableElementData(visualElement.GetBindableChilds());
1819

1920
return visualElement;
2021
}
@@ -42,7 +43,7 @@ public static VisualElement InitializeBindableElement(this VisualElement visualE
4243
initializable.Initialize();
4344
}
4445

45-
var bindableElements = (List<IBindableElement>) visualElement.userData;
46+
var bindableElements = ((BindableElementData) visualElement.userData).BindableElements;
4647

4748
for (var i = 0; i < bindableElements.Count; i++)
4849
{
@@ -55,11 +56,21 @@ public static VisualElement InitializeBindableElement(this VisualElement visualE
5556
return visualElement;
5657
}
5758

59+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
60+
public static TBindingContext GetBindingContext<TBindingContext>(this VisualElement visualElement)
61+
where TBindingContext : IBindingContext
62+
{
63+
return (TBindingContext) ((BindableElementData) visualElement.userData).BindingContext;
64+
}
65+
5866
[MethodImpl(MethodImplOptions.AggressiveInlining)]
5967
public static void SetChildsBindingContext(this VisualElement visualElement, IBindingContext bindingContext,
6068
IObjectProvider objectProvider)
6169
{
62-
var bindableElements = (List<IBindableElement>) visualElement.userData;
70+
var bindableElementData = (BindableElementData) visualElement.userData;
71+
bindableElementData.BindingContext = bindingContext;
72+
73+
var bindableElements = bindableElementData.BindableElements;
6374

6475
for (var i = 0; i < bindableElements.Count; i++)
6576
{
@@ -70,7 +81,10 @@ public static void SetChildsBindingContext(this VisualElement visualElement, IBi
7081
[MethodImpl(MethodImplOptions.AggressiveInlining)]
7182
public static void ResetChildsBindingContext(this VisualElement visualElement, IObjectProvider objectProvider)
7283
{
73-
var bindableElements = (List<IBindableElement>) visualElement.userData;
84+
var bindableElementData = (BindableElementData) visualElement.userData;
85+
bindableElementData.BindingContext = default;
86+
87+
var bindableElements = bindableElementData.BindableElements;
7488

7589
for (var i = 0; i < bindableElements.Count; i++)
7690
{
@@ -82,7 +96,8 @@ public static void ResetChildsBindingContext(this VisualElement visualElement, I
8296
public static void DisposeBindableElement(this VisualElement visualElement,
8397
[CanBeNull] IObjectProvider objectProvider = null)
8498
{
85-
var bindableElements = (List<IBindableElement>) visualElement.userData;
99+
var bindableElementData = (BindableElementData) visualElement.userData;
100+
var bindableElements = bindableElementData.BindableElements;
86101

87102
for (var i = 0; i < bindableElements.Count; i++)
88103
{
@@ -104,8 +119,8 @@ public static void DisposeBindableElement(this VisualElement visualElement,
104119
disposable.Dispose();
105120
}
106121

107-
bindableElements.Clear();
108-
visualElement.userData = null;
122+
bindableElementData.Dispose();
123+
visualElement.userData = default;
109124
}
110125

111126
[MethodImpl(MethodImplOptions.AggressiveInlining)]

0 commit comments

Comments
 (0)