Răsfoiți Sursa

Fixed RefreshObject when Equality method is overridden in model objects
Now when you call RefreshObject the Branch.Model is always updated to the latest reference even when Equals indicates we already have it in children

tznind 4 ani în urmă
părinte
comite
8ce042eb52
2 a modificat fișierele cu 66 adăugiri și 2 ștergeri
  1. 11 2
      Terminal.Gui/Views/TreeView.cs
  2. 55 0
      UnitTests/TreeViewTests.cs

+ 11 - 2
Terminal.Gui/Views/TreeView.cs

@@ -595,8 +595,17 @@ namespace Terminal.Gui {
 				}
 				
 				// New children need to be added
-				foreach(var toAdd in newChildren.Except(ChildBranches.Keys).ToArray())
-					ChildBranches.Add(toAdd,new Branch(tree,this,toAdd));
+				foreach(var newChild in newChildren)
+				{
+					// If we don't know about the child yet we need a new branch
+					if (!ChildBranches.ContainsKey (newChild)) {
+						ChildBranches.Add(newChild,new Branch(tree,this,newChild));
+					}
+					else{
+						//we already have this object but update the reference anyway incase Equality match but the references are new
+						ChildBranches[newChild].Model = newChild;
+					}					
+				}
 			}
 			
 		}

+ 55 - 0
UnitTests/TreeViewTests.cs

@@ -213,5 +213,60 @@ namespace UnitTests {
 			Assert.Empty(tree.GetChildren(c1));
 			Assert.Empty(tree.GetChildren(c2));
 		}
+
+
+		/// <summary>
+		/// Simulates behind the scenes changes to an object (which children it has) and how to sync that into the tree using <see cref="TreeView.RefreshObject(object, bool)"/>
+		/// </summary>
+		[Fact]
+		public void RefreshObject_EqualityTest()
+		{
+			var obj1 = new EqualityTestObject(){Name="Bob",Age=1 };
+			var obj2 = new EqualityTestObject(){Name="Bob",Age=2 };;
+
+			string root = "root";
+			
+			var tree = new TreeView();
+			tree.ChildrenGetter = (s)=>  ReferenceEquals(s , root) ? new object[]{obj1 } : null;
+			tree.AddObject(root);
+
+			// Tree is not expanded so the root has no children yet
+			Assert.Empty(tree.GetChildren(root));
+
+
+			tree.Expand(root);
+
+			// now that the tree is expanded we should get our child returned
+			Assert.Equal(1,tree.GetChildren(root).Count(child=>ReferenceEquals(obj1,child)));
+
+			// change the getter to return an Equal object (but not the same reference - obj2)
+			tree.ChildrenGetter = (s)=>  ReferenceEquals(s , root) ? new object[]{obj2 } : null;
+
+			// tree has cached the knowledge of what children the root has so won't know about the change (we still get obj1)
+			Assert.Equal(1,tree.GetChildren(root).Count(child=>ReferenceEquals(obj1,child)));
+
+			// now that we refresh the root we should get the new child reference (obj2)
+			tree.RefreshObject(root);
+			Assert.Equal(1,tree.GetChildren(root).Count(child=>ReferenceEquals(obj2,child)));
+
+		}
+
+		/// <summary>
+		/// Test object which considers for equality only <see cref="Name"/>
+		/// </summary>
+		private class EqualityTestObject
+		{
+			public string Name { get;set;}
+			public int Age { get;set;}
+
+			public override int GetHashCode ()
+			{
+				return Name?.GetHashCode()??base.GetHashCode ();
+			}
+			public override bool Equals (object obj)
+			{
+				return obj is EqualityTestObject eto && Equals(Name, eto.Name);
+			}
+		}
 	}
 }