From 33032f7b76f171427aa580ca9049c9710ba09114 Mon Sep 17 00:00:00 2001 From: Jtfk Date: Sun, 4 Jun 2023 16:30:48 +0800 Subject: [PATCH] fix(module: tree): fix IList `DataSource` cannot be modify in place (#3275) * fix(module: tree): skip `ToList()` when type is `IList` This allow DataSource to be modify by TreeNode draggable methods. * test(module: tree): add test for TreeNode modify DataSource --- components/tree/TreeNode.razor.cs | 11 ++- tests/AntDesign.Tests/Tree/TreeTests.razor | 104 +++++++++++++++++++++ 2 files changed, 113 insertions(+), 2 deletions(-) create mode 100644 tests/AntDesign.Tests/Tree/TreeTests.razor diff --git a/components/tree/TreeNode.razor.cs b/components/tree/TreeNode.razor.cs index 9f5ed796..44041f72 100644 --- a/components/tree/TreeNode.razor.cs +++ b/components/tree/TreeNode.razor.cs @@ -713,7 +713,14 @@ namespace AntDesign get { if (TreeComponent.ChildrenExpression != null) - return TreeComponent.ChildrenExpression(this)?.ToList() ?? new List(); + { + var childItems = TreeComponent.ChildrenExpression(this); + if (childItems is IList list) + { + return list; + } + return childItems?.ToList() ?? new List(); + } else return new List(); } @@ -728,7 +735,7 @@ namespace AntDesign if (this.ParentNode != null) return this.ParentNode.ChildDataItems; else - return this.TreeComponent.DataSource.ToList(); + return this.TreeComponent.DataSource as IList ?? this.TreeComponent.DataSource.ToList(); } #endregion data binding diff --git a/tests/AntDesign.Tests/Tree/TreeTests.razor b/tests/AntDesign.Tests/Tree/TreeTests.razor new file mode 100644 index 00000000..cca1116f --- /dev/null +++ b/tests/AntDesign.Tests/Tree/TreeTests.razor @@ -0,0 +1,104 @@ +@inherits AntDesignTestBase + +@code { + + record Item(string Name) + { + public List Children { get; set; } = new(); + }; + + [Fact] + public async Task Parent_MoveDown_item_mutate_datasource() + { + var data = new List + { + new Item("Item 1"), + new Item("Item 2"), + }; + + var cut = Render>(@); + var firstItem = cut.FindComponent>(); + + var firstItemIndex = data.IndexOf(firstItem.Instance.DataItem) + 1; + firstItem.Instance.MoveDown(); + + var resultList = firstItem.Instance.GetParentChildDataItems(); + resultList.Should().HaveElementAt(firstItemIndex, firstItem.Instance.DataItem, "DataSource should be mutated"); + } + + [Fact] + public async Task Parent_Remove_item_mutate_datasource() + { + var data = new List + { + new Item("Item 1"), + new Item("Item 2"), + }; + + var cut = Render>(@); + var firstItem = cut.FindComponent>(); + firstItem.Instance.Remove(); + + data.Should().NotContain(firstItem.Instance.DataItem, "Item should be removed in DataSource"); + } + + [Fact] + public async Task Children_MoveDown_item_mutate_datasource() + { + var data = new List + { + new Item("Item 1") + { + Children = new List + { + new Item("Child 1-1"), + new Item("Child 1-2"), + } + }, + }; + + var cut = Render>( + @ + ); + + var treeNodes = cut.FindComponents>(); + var childComponent = treeNodes.First(component => component.Instance.DataItem.Name.Equals("Child 1-1")); + + var childItemIndex = data[0].Children.IndexOf(childComponent.Instance.DataItem) + 1; + childComponent.Instance.MoveDown(); + + var resultList = childComponent.Instance.GetParentChildDataItems(); + resultList.Should().HaveElementAt(childItemIndex, childComponent.Instance.DataItem, "DataSource should be mutated"); + } + + [Fact] + public async Task Children_Remove_item_mutate_datasource() + { + var data = new List + { + new Item("Item 1") + { + Children = new List + { + new Item("Child 1-1"), + new Item("Child 1-2"), + } + }, + }; + + var cut = Render>( + @ + ); + + var treeNodes = cut.FindComponents>(); + var childComponent = treeNodes.First(component => component.Instance.DataItem.Name.Equals("Child 1-2")); + childComponent.Instance.Remove(); + + data[0].Children.Should().NotContain(childComponent.Instance.DataItem, "Item should be removed in DataSource"); + } + +}