Skip to content

Commit 4fb9f20

Browse files
committed
Add TItem and TCollection BindableListView.
1 parent ac053f0 commit 4fb9f20

File tree

6 files changed

+214
-174
lines changed

6 files changed

+214
-174
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,150 +1,11 @@
1-
using System;
2-
using System.Collections.Generic;
3-
using System.Collections.ObjectModel;
4-
using System.Collections.Specialized;
5-
using UnityEngine.UIElements;
1+
using System.Collections.ObjectModel;
62
using UnityMvvmToolkit.Common.Interfaces;
7-
using UnityMvvmToolkit.Core;
8-
using UnityMvvmToolkit.Core.Extensions;
9-
using UnityMvvmToolkit.Core.Interfaces;
10-
using UnityMvvmToolkit.UITK.Extensions;
113

124
namespace UnityMvvmToolkit.UITK.BindableUIElements
135
{
14-
public abstract partial class BindableListView<TItemBindingContext> : ListView, IBindableCollection,
15-
IInitializable, IDisposable where TItemBindingContext : ICollectionItem
6+
public abstract partial class BindableListView<TItemBindingContext> :
7+
BindableListView<TItemBindingContext, ObservableCollection<TItemBindingContext>>
8+
where TItemBindingContext : ICollectionItem
169
{
17-
private VisualTreeAsset _itemTemplate;
18-
19-
private PropertyBindingData _itemsSourceBindingData;
20-
private ObservableCollection<TItemBindingContext> _itemsSource;
21-
private IReadOnlyProperty<ObservableCollection<TItemBindingContext>> _itemsSourceProperty;
22-
23-
private IObjectProvider _objectProvider;
24-
private List<VisualElement> _itemAssets;
25-
private Dictionary<int, TItemBindingContext> _activeItems;
26-
27-
public virtual void Initialize()
28-
{
29-
_itemAssets = new List<VisualElement>();
30-
_activeItems = new Dictionary<int, TItemBindingContext>();
31-
}
32-
33-
public virtual void Dispose()
34-
{
35-
for (var i = 0; i < _itemAssets.Count; i++)
36-
{
37-
_itemAssets[i].DisposeBindableElement(_objectProvider);
38-
}
39-
40-
_itemAssets.Clear();
41-
_activeItems.Clear();
42-
}
43-
44-
public virtual void SetBindingContext(IBindingContext context, IObjectProvider objectProvider)
45-
{
46-
if (string.IsNullOrWhiteSpace(BindingItemsSourcePath))
47-
{
48-
return;
49-
}
50-
51-
_itemsSourceBindingData ??= BindingItemsSourcePath.ToPropertyBindingData();
52-
_itemTemplate ??= objectProvider.GetCollectionItemTemplate<TItemBindingContext, VisualTreeAsset>();
53-
54-
_objectProvider = objectProvider;
55-
56-
_itemsSourceProperty = objectProvider
57-
.RentReadOnlyProperty<ObservableCollection<TItemBindingContext>>(context, _itemsSourceBindingData);
58-
_itemsSource = _itemsSourceProperty.Value;
59-
_itemsSource.CollectionChanged += OnItemsCollectionChanged;
60-
61-
itemsSource = _itemsSource;
62-
makeItem += OnMakeItem;
63-
bindItem += OnBindItem;
64-
unbindItem += OnUnbindItem;
65-
}
66-
67-
public virtual void ResetBindingContext(IObjectProvider objectProvider)
68-
{
69-
if (_itemsSourceProperty is null)
70-
{
71-
return;
72-
}
73-
74-
_itemsSource.CollectionChanged -= OnItemsCollectionChanged;
75-
76-
makeItem -= OnMakeItem;
77-
bindItem -= OnBindItem;
78-
unbindItem -= OnUnbindItem;
79-
itemsSource = Array.Empty<TItemBindingContext>();
80-
81-
objectProvider.ReturnReadOnlyProperty(_itemsSourceProperty);
82-
83-
_itemTemplate = null;
84-
_objectProvider = null;
85-
86-
_itemsSource = null;
87-
_itemsSourceProperty = null;
88-
}
89-
90-
protected virtual VisualElement MakeItem(VisualTreeAsset itemTemplate)
91-
{
92-
return itemTemplate
93-
.InstantiateBindableElement()
94-
.InitializeBindableElement();
95-
}
96-
97-
protected virtual void BindItem(VisualElement item, int index, TItemBindingContext bindingContext,
98-
IObjectProvider objectProvider)
99-
{
100-
item.SetChildsBindingContext(bindingContext, objectProvider);
101-
}
102-
103-
protected virtual void UnbindItem(VisualElement item, int index, TItemBindingContext bindingContext,
104-
IObjectProvider objectProvider)
105-
{
106-
item.ResetChildsBindingContext(objectProvider);
107-
}
108-
109-
protected virtual void OnItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
110-
{
111-
#if UNITY_2021
112-
if (e.Action is NotifyCollectionChangedAction.Remove or NotifyCollectionChangedAction.Reset)
113-
{
114-
Rebuild();
115-
return;
116-
}
117-
#endif
118-
RefreshItems();
119-
}
120-
121-
private VisualElement OnMakeItem()
122-
{
123-
var item = MakeItem(_itemTemplate);
124-
125-
_itemAssets.Add(item);
126-
127-
return item;
128-
}
129-
130-
private void OnBindItem(VisualElement item, int index)
131-
{
132-
var itemId = item.GetHashCode();
133-
var itemBindingContext = _itemsSource[index];
134-
135-
_activeItems.Add(itemId, itemBindingContext);
136-
137-
BindItem(item, index, itemBindingContext, _objectProvider);
138-
}
139-
140-
private void OnUnbindItem(VisualElement item, int index)
141-
{
142-
var itemId = item.GetHashCode();
143-
144-
if (_activeItems.Remove(itemId, out var itemBindingContext))
145-
{
146-
UnbindItem(item, index, itemBindingContext, _objectProvider);
147-
}
148-
}
14910
}
15011
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
using System;
2+
using System.Collections;
3+
using System.Collections.Generic;
4+
using System.Collections.Specialized;
5+
using UnityEngine.UIElements;
6+
using UnityMvvmToolkit.Common.Interfaces;
7+
using UnityMvvmToolkit.Core;
8+
using UnityMvvmToolkit.Core.Extensions;
9+
using UnityMvvmToolkit.Core.Interfaces;
10+
using UnityMvvmToolkit.UITK.Extensions;
11+
12+
namespace UnityMvvmToolkit.UITK.BindableUIElements
13+
{
14+
public abstract partial class BindableListView<TItemBindingContext, TCollection> :
15+
ListView, IBindableCollection, IInitializable, IDisposable
16+
where TItemBindingContext : ICollectionItem
17+
where TCollection : IList<TItemBindingContext>, IList, INotifyCollectionChanged
18+
{
19+
private VisualTreeAsset _itemTemplate;
20+
21+
private IObjectProvider _objectProvider;
22+
private List<VisualElement> _itemAssets;
23+
private IList<TItemBindingContext> _itemsSource;
24+
private Dictionary<int, TItemBindingContext> _activeItems;
25+
26+
protected PropertyBindingData _itemsSourceBindingData;
27+
protected IReadOnlyProperty<TCollection> _itemsSourceProperty;
28+
29+
public virtual void Initialize()
30+
{
31+
_itemAssets = new List<VisualElement>();
32+
_activeItems = new Dictionary<int, TItemBindingContext>();
33+
}
34+
35+
public virtual void Dispose()
36+
{
37+
for (var i = 0; i < _itemAssets.Count; i++)
38+
{
39+
_itemAssets[i].DisposeBindableElement(_objectProvider);
40+
}
41+
42+
_itemAssets.Clear();
43+
_activeItems.Clear();
44+
}
45+
46+
public virtual void SetBindingContext(IBindingContext context, IObjectProvider objectProvider)
47+
{
48+
if (string.IsNullOrWhiteSpace(BindingItemsSourcePath))
49+
{
50+
return;
51+
}
52+
53+
_itemsSourceBindingData ??= BindingItemsSourcePath.ToPropertyBindingData();
54+
_itemTemplate ??= objectProvider.GetCollectionItemTemplate<TItemBindingContext, VisualTreeAsset>();
55+
56+
_objectProvider = objectProvider;
57+
58+
_itemsSourceProperty = objectProvider.RentReadOnlyProperty<TCollection>(context, _itemsSourceBindingData);
59+
_itemsSourceProperty.Value.CollectionChanged += OnItemsCollectionChanged;
60+
_itemsSource = _itemsSourceProperty.Value;
61+
62+
itemsSource = _itemsSourceProperty.Value;
63+
makeItem += OnMakeItem;
64+
bindItem += OnBindItem;
65+
unbindItem += OnUnbindItem;
66+
}
67+
68+
public virtual void ResetBindingContext(IObjectProvider objectProvider)
69+
{
70+
if (_itemsSourceProperty is null)
71+
{
72+
return;
73+
}
74+
75+
_itemsSourceProperty.Value.CollectionChanged -= OnItemsCollectionChanged;
76+
77+
makeItem -= OnMakeItem;
78+
bindItem -= OnBindItem;
79+
unbindItem -= OnUnbindItem;
80+
itemsSource = Array.Empty<TItemBindingContext>();
81+
82+
objectProvider.ReturnReadOnlyProperty(_itemsSourceProperty);
83+
84+
_itemTemplate = null;
85+
_objectProvider = null;
86+
87+
_itemsSource = default;
88+
_itemsSourceProperty = null;
89+
}
90+
91+
protected virtual VisualElement MakeItem(VisualTreeAsset itemTemplate)
92+
{
93+
return itemTemplate
94+
.InstantiateBindableElement()
95+
.InitializeBindableElement();
96+
}
97+
98+
protected virtual void BindItem(VisualElement item, int index, TItemBindingContext bindingContext,
99+
IObjectProvider objectProvider)
100+
{
101+
item.SetChildsBindingContext(bindingContext, objectProvider);
102+
}
103+
104+
protected virtual void UnbindItem(VisualElement item, int index, TItemBindingContext bindingContext,
105+
IObjectProvider objectProvider)
106+
{
107+
item.ResetChildsBindingContext(objectProvider);
108+
}
109+
110+
protected virtual void OnItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
111+
{
112+
#if UNITY_2021
113+
if (e.Action is NotifyCollectionChangedAction.Remove or NotifyCollectionChangedAction.Reset)
114+
{
115+
Rebuild();
116+
return;
117+
}
118+
#endif
119+
RefreshItems();
120+
}
121+
122+
private VisualElement OnMakeItem()
123+
{
124+
var item = MakeItem(_itemTemplate);
125+
126+
_itemAssets.Add(item);
127+
128+
return item;
129+
}
130+
131+
private void OnBindItem(VisualElement item, int index)
132+
{
133+
var itemId = item.GetHashCode();
134+
var itemBindingContext = _itemsSource[index];
135+
136+
if (_activeItems.TryAdd(itemId, itemBindingContext))
137+
{
138+
BindItem(item, index, itemBindingContext, _objectProvider);
139+
}
140+
}
141+
142+
private void OnUnbindItem(VisualElement item, int index)
143+
{
144+
var itemId = item.GetHashCode();
145+
146+
if (_activeItems.Remove(itemId, out var itemBindingContext))
147+
{
148+
UnbindItem(item, index, itemBindingContext, _objectProvider);
149+
}
150+
}
151+
}
152+
}

src/UnityMvvmToolkit.UnityPackage/Assets/Plugins/UnityMvvmToolkit/Runtime/UITK/BindableUIElements/BindableListView.TItem.TCollection.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/Uxmls/BindableListView.T.Uxml.cs

Lines changed: 7 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,20 @@
1-
using UnityEngine.UIElements;
2-
using UnityMvvmToolkit.UITK.Extensions;
1+
using System.Collections.ObjectModel;
2+
using UnityMvvmToolkit.Common.Interfaces;
33

44
namespace UnityMvvmToolkit.UITK.BindableUIElements
55
{
6-
partial class BindableListView<TItemBindingContext>
6+
partial class BindableListView<TItemBindingContext> where TItemBindingContext : ICollectionItem
77
{
8-
public string BindingItemsSourcePath { get; private set; }
9-
108
#if UNITY_2023_2_OR_NEWER
119
[System.Serializable]
12-
public new class UxmlSerializedData : ListView.UxmlSerializedData
10+
public new class UxmlSerializedData :
11+
BindableListView<TItemBindingContext, ObservableCollection<TItemBindingContext>>.UxmlSerializedData
1312
{
14-
// ReSharper disable once InconsistentNaming
15-
#pragma warning disable 649
16-
[UnityEngine.SerializeField] private string BindingItemsSourcePath;
17-
#pragma warning restore 649
18-
19-
public override void Deserialize(object visualElement)
20-
{
21-
base.Deserialize(visualElement);
22-
23-
visualElement
24-
.As<BindableListView<TItemBindingContext>>()
25-
.BindingItemsSourcePath = BindingItemsSourcePath;
26-
}
2713
}
2814
#else
29-
public new class UxmlTraits : ListView.UxmlTraits
15+
public new class UxmlTraits :
16+
BindableListView<TItemBindingContext, ObservableCollection<TItemBindingContext>>.UxmlTraits
3017
{
31-
private readonly UxmlStringAttributeDescription _bindingItemsSourceAttribute = new()
32-
{ name = "binding-items-source-path", defaultValue = "" };
33-
34-
public override void Init(VisualElement visualElement, IUxmlAttributes bag, CreationContext context)
35-
{
36-
base.Init(visualElement, bag, context);
37-
38-
visualElement
39-
.As<BindableListView<TItemBindingContext>>()
40-
.BindingItemsSourcePath = _bindingItemsSourceAttribute.GetValueFromBag(bag, context);
41-
}
4218
}
4319
#endif
4420
}

0 commit comments

Comments
 (0)