Skip to content

Commit 8e8f253

Browse files
committed
Fix #49 - Wrong number of children instantiated in container view.
- Add container binding test scripts and related functionality - Introduced FastSpawnTestRunner to generate random items for testing container bindings. - Implemented LifetimeTracker to log the lifecycle of tested children. - Created EditorContainerBindingTest to validate container behavior with preoccupied items. - Enhanced RuntimeContainerBindingsTest to include tests for preoccupied containers. - Updated Item prefab to include LifetimeTracker component.
1 parent 8c70fc5 commit 8e8f253

13 files changed

Lines changed: 1837 additions & 401 deletions

Runtime/Scripts/Bindings/ComponentPropertyBinding.cs

Lines changed: 120 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -2,151 +2,150 @@
22
using System.Linq;
33
using System.Reflection;
44
using UnityEngine;
5-
using UnityEngine.UIElements;
65

76
namespace JH.DataBinding
87
{
9-
[Serializable]
10-
public class ComponentPropertyBinding
11-
{
12-
[SerializeField]
13-
[BindingSourcePath]
14-
private string sourcePath;
8+
[Serializable]
9+
public class ComponentPropertyBinding
10+
{
11+
[SerializeField]
12+
[BindingSourcePath]
13+
private string sourcePath;
1514

16-
[SerializeField]
17-
private GameObject targetGameObject;
15+
[SerializeField]
16+
private GameObject targetGameObject;
1817

19-
[SerializeField]
20-
[BindingTargetComponent]
21-
private Component targetComponent;
18+
[SerializeField]
19+
[BindingTargetComponent]
20+
private Component targetComponent;
2221

23-
[SerializeField]
24-
[BindingTargetPath]
25-
private string targetPath;
22+
[SerializeField]
23+
[BindingTargetPath]
24+
private string targetPath;
2625

27-
private object dataSource;
26+
private object dataSource;
2827

29-
private MethodInfo[] dataSourcePropertyAccessors = Array.Empty<MethodInfo>();
30-
private MethodInfo[] targetPropertyAccessors = Array.Empty<MethodInfo>();
28+
private MethodInfo[] dataSourcePropertyAccessors = Array.Empty<MethodInfo>();
29+
private MethodInfo[] targetPropertyAccessors = Array.Empty<MethodInfo>();
3130

32-
public object DataSource
31+
public object DataSource
32+
{
33+
get => dataSource;
34+
set
35+
{
36+
if (dataSource != value)
3337
{
34-
get => dataSource;
35-
set
36-
{
37-
if (dataSource != value)
38-
{
39-
dataSource = value;
40-
41-
BindSource();
42-
}
43-
}
38+
dataSource = value;
39+
40+
BindSource();
4441
}
42+
}
43+
}
4544

46-
public string SourcePath
45+
public string SourcePath
46+
{
47+
get => sourcePath;
48+
set
49+
{
50+
if (sourcePath != value)
4751
{
48-
get => sourcePath;
49-
set
50-
{
51-
if (sourcePath != value)
52-
{
53-
sourcePath = value;
54-
55-
BindSource();
56-
}
57-
}
52+
sourcePath = value;
53+
54+
BindSource();
5855
}
56+
}
57+
}
5958

60-
public GameObject TargetGameObject
59+
public GameObject TargetGameObject
60+
{
61+
get => targetGameObject;
62+
set
63+
{
64+
if (targetGameObject != value)
6165
{
62-
get => targetGameObject;
63-
set
64-
{
65-
if (targetGameObject != value)
66-
{
67-
targetGameObject = value;
68-
targetComponent = null;
69-
70-
BindTarget();
71-
}
72-
}
66+
targetGameObject = value;
67+
targetComponent = null;
68+
69+
BindTarget();
7370
}
74-
public Component TargetComponent
71+
}
72+
}
73+
public Component TargetComponent
74+
{
75+
get => targetComponent;
76+
set
77+
{
78+
if (targetComponent != value)
7579
{
76-
get => targetComponent;
77-
set
78-
{
79-
if (targetComponent != value)
80-
{
81-
targetComponent = value;
82-
targetGameObject = value.gameObject;
83-
84-
BindTarget();
85-
}
86-
}
87-
}
80+
targetComponent = value;
81+
targetGameObject = value.gameObject;
8882

89-
public string TargetPath
90-
{
91-
get => targetPath;
92-
set
93-
{
94-
if (targetPath != value)
95-
{
96-
targetPath = value;
97-
98-
BindTarget();
99-
}
100-
}
83+
BindTarget();
10184
}
85+
}
86+
}
10287

103-
private void BindSource()
88+
public string TargetPath
89+
{
90+
get => targetPath;
91+
set
92+
{
93+
if (targetPath != value)
10494
{
105-
if (dataSource != null && !String.IsNullOrEmpty(sourcePath))
106-
{
107-
dataSourcePropertyAccessors = dataSource
108-
.ResolvePublicPropertyPath(SourcePath, PathResolveOperation.GetValue)
109-
.ToArray();
110-
}
111-
else
112-
{
113-
dataSourcePropertyAccessors = Array.Empty<MethodInfo>();
114-
}
115-
}
95+
targetPath = value;
11696

117-
private void BindTarget()
118-
{
119-
if (targetComponent != null && !String.IsNullOrEmpty(targetPath))
120-
{
121-
targetPropertyAccessors = targetComponent
122-
.ResolvePublicPropertyPath(targetPath, PathResolveOperation.SetValue)
123-
.ToArray();
124-
}
125-
else
126-
{
127-
targetPropertyAccessors = Array.Empty<MethodInfo>();
128-
}
97+
BindTarget();
12998
}
99+
}
100+
}
130101

131-
public void UpdateBinding()
132-
{
133-
if (dataSourcePropertyAccessors.Length == 0)
134-
{
135-
return;
136-
}
137-
138-
if (targetPropertyAccessors.Length == 0)
139-
{
140-
BindTarget();
141-
}
142-
143-
if (targetPropertyAccessors.Length == 0)
144-
{
145-
return;
146-
}
147-
148-
var value = dataSourcePropertyAccessors.InvokeGetAccessChain(dataSource);
149-
targetPropertyAccessors.InvokeSetAccessChain(targetComponent, value);
150-
}
102+
private void BindSource()
103+
{
104+
if (dataSource != null && !String.IsNullOrEmpty(sourcePath))
105+
{
106+
dataSourcePropertyAccessors = dataSource
107+
.ResolvePublicPropertyPath(SourcePath, PathResolveOperation.GetValue)
108+
.ToArray();
109+
}
110+
else
111+
{
112+
dataSourcePropertyAccessors = Array.Empty<MethodInfo>();
113+
}
114+
}
115+
116+
private void BindTarget()
117+
{
118+
if (targetComponent != null && !String.IsNullOrEmpty(targetPath))
119+
{
120+
targetPropertyAccessors = targetComponent
121+
.ResolvePublicPropertyPath(targetPath, PathResolveOperation.SetValue)
122+
.ToArray();
123+
}
124+
else
125+
{
126+
targetPropertyAccessors = Array.Empty<MethodInfo>();
127+
}
128+
}
129+
130+
public void UpdateBinding()
131+
{
132+
if (dataSourcePropertyAccessors.Length == 0)
133+
{
134+
return;
135+
}
136+
137+
if (targetPropertyAccessors.Length == 0)
138+
{
139+
BindTarget();
140+
}
141+
142+
if (targetPropertyAccessors.Length == 0)
143+
{
144+
return;
145+
}
146+
147+
var value = dataSourcePropertyAccessors.InvokeGetAccessChain(dataSource);
148+
targetPropertyAccessors.InvokeSetAccessChain(targetComponent, value);
151149
}
150+
}
152151
}

Runtime/Scripts/Bindings/ContainerPropertyBinding.cs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -112,20 +112,18 @@ private void AddMissingChildren(int numberOfRequiredChildren)
112112

113113
private void RemoveSuperfluousChildren(int numberOfChildrenToKeep)
114114
{
115-
for (
116-
var childIndex = numberOfChildrenToKeep;
117-
childIndex < TargetContainer.childCount;
118-
++childIndex
119-
)
115+
while (TargetContainer.childCount > numberOfChildrenToKeep)
120116
{
121-
var childView = TargetContainer.GetChild(childIndex).GetComponent<View>();
117+
var child = TargetContainer.GetChild(TargetContainer.childCount - 1);
118+
var childView = child.GetComponent<View>();
122119

123120
if (childView != null)
124121
{
125122
childView.DataSource = null;
126123
}
127124

128-
UnityEngine.Object.Destroy(TargetContainer.GetChild(childIndex).gameObject);
125+
child.SetParent(null);
126+
UnityEngine.Object.Destroy(child.gameObject);
129127
}
130128
}
131129
}

0 commit comments

Comments
 (0)