Skip to content

Commit 5b51d66

Browse files
committed
Adding example failing tests
Fixing minor code issue
1 parent cab7a60 commit 5b51d66

File tree

6 files changed

+124
-19
lines changed

6 files changed

+124
-19
lines changed

src/MaterialDesignThemes.Wpf/TreeListView.cs

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public double LevelIndentSize
2020

2121
internal TreeListViewItemsCollection? InternalItemsSource { get; set; }
2222

23-
internal bool IsCollapsingItem { get; set; } = false;
23+
private bool IsCollapsingItem { get; set; }
2424
public new IList SelectedItems
2525
{
2626
get => (IList)GetValue(SelectedItemsProperty);
@@ -88,16 +88,13 @@ private void TreeListView_SelectionChanged(object sender, SelectionChangedEventA
8888
// Add newly selected
8989
foreach (var item in e.AddedItems)
9090
{
91-
if (!SelectedItems.Contains(item))
92-
{
93-
SelectedItems.Add(item);
94-
}
91+
SelectedItems.Add(item);
9592
}
9693
}
9794

9895
private void SelectedItems_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
9996
{
100-
// NB: Everytime we modify the base.SelectedItems we have to unsubscribe from the SelectionChanged event
97+
// NB: Every time we modify the base.SelectedItems we have to unsubscribe from the SelectionChanged event
10198
// The base.SelectedItems only contains the visually selected items,
10299
// while the SelectedItems contains all selected items, even ones which are not "visible"
103100
this.SelectionChanged -= TreeListView_SelectionChanged;
@@ -122,10 +119,7 @@ private void SelectedItems_CollectionChanged(object? sender, NotifyCollectionCha
122119

123120
foreach (var item in e.NewItems ?? Array.Empty<object>())
124121
{
125-
if (!base.SelectedItems.Contains(item))
126-
{
127-
base.SelectedItems.Add(item);
128-
}
122+
base.SelectedItems.Add(item);
129123
}
130124
}
131125

@@ -210,7 +204,7 @@ internal void ItemExpandedChanged(TreeListViewItem item)
210204
{
211205
itemsSource.InsertWithLevel(i + index + 1, children[i], parentLevel + 1);
212206
}
213-
// if a node, which has a selected childs, is expanded (added) we need to visually select the child (i.e.: update base.SelectedItems)
207+
// if a node, which has a selected child, is expanded (added) we need to visually select the child (i.e.: update base.SelectedItems)
214208
SyncUISelectionWithSelectedItems();
215209
}
216210
else
@@ -343,7 +337,7 @@ static int GetChildrenAndGrandChildrenCountOfPriorSiblings(TreeListViewItemsColl
343337

344338
private List<object?> GetExpandedChildrenAndGrandChildren(object? dataItem)
345339
{
346-
List<object?> expandedChildren = new();
340+
List<object?> expandedChildren = [];
347341
if (dataItem is null || ItemContainerGenerator.ContainerFromItem(dataItem) is not TreeListViewItem { IsExpanded: true } container)
348342
return expandedChildren;
349343

tests/MaterialDesignThemes.UITests/WPF/TreeListViews/TreeListViewDataBinding.xaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
<StackPanel Grid.Row="1" Orientation="Horizontal">
3333
<Button Content="Add" Click="Add_OnClick" />
3434
<Button Content="Add with Children" Click="AddWithChildren_OnClick" />
35+
<Button Content="Add Duplicate" Click="AddDuplicate_OnClick" />
3536
<Button Content="Remove" Click="Remove_OnClick" />
3637
<Button Content="Replace" Click="Replace_OnClick" />
3738
<Button Content="Down" Click="MoveDown_OnClick" />

tests/MaterialDesignThemes.UITests/WPF/TreeListViews/TreeListViewDataBinding.xaml.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ public TreeListViewDataBinding()
2121

2222
public void Add_OnClick(object sender, EventArgs e) => AddItem();
2323
public void AddWithChildren_OnClick(object sender, EventArgs e) => AddItemWithChildren();
24+
public void AddDuplicate_OnClick(object sender, EventArgs e) => AddDuplicateItem();
2425

2526
private void AddItem()
2627
{
@@ -34,6 +35,23 @@ private void AddItem()
3435
}
3536
}
3637

38+
private void AddDuplicateItem()
39+
{
40+
if (TreeListView.SelectedItem is TreeItem selectedItem)
41+
{
42+
if (selectedItem.Parent is { } parent)
43+
{
44+
int childIndex = parent.Children.IndexOf(selectedItem);
45+
parent.Children.Insert(childIndex + 1, selectedItem);
46+
}
47+
else
48+
{
49+
int itemIndex = Items.IndexOf(selectedItem);
50+
Items.Insert(itemIndex + 1, selectedItem);
51+
}
52+
}
53+
}
54+
3755
private void AddItemWithChildren()
3856
{
3957
TreeItem parent = new(Items.Count.ToString(), null)

tests/MaterialDesignThemes.UITests/WPF/TreeListViews/TreeListViewImplicitTemplate.xaml.cs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,9 @@ public void Remove_OnClick(object sender, EventArgs e)
4141
}
4242
}
4343

44-
private void RemoveItem(IList<TreeItem> items, TreeItem toRemove)
44+
private static void RemoveItem(IList<TreeItem> items, TreeItem toRemove)
4545
{
46-
if (items.Contains(toRemove))
47-
{
48-
items.Remove(toRemove);
49-
}
46+
items.Remove(toRemove);
5047
foreach (TreeItem item in items)
5148
{
5249
RemoveItem(item.Children, toRemove);

tests/MaterialDesignThemes.UITests/WPF/TreeListViews/TreeListViewTests.cs

Lines changed: 96 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
using System.Collections;
21
using System.ComponentModel;
32
using System.Windows.Media;
43

@@ -1118,6 +1117,102 @@ static void AssertSelectedItems(TreeListView treeListView)
11181117
}
11191118
}
11201119

1120+
[Fact]
1121+
public async Task TreeListView_CollapsingParentAndMovingSelection_ClearsSelectionsFromHiddenChildNode()
1122+
{
1123+
await using var recorder = new TestRecorder(App);
1124+
1125+
IVisualElement<Grid> root = (await LoadUserControl(typeof(TreeListViewDataBinding))).As<Grid>();
1126+
IVisualElement<TreeListView> treeListView = await root.GetElement<TreeListView>();
1127+
IVisualElement<Button> addButton = await root.GetElement(ElementQuery.PropertyExpression<Button>(x => x.Content, "Add"));
1128+
1129+
IVisualElement<TreeListViewItem> item1 = await treeListView.GetElement<TreeListViewItem>("/TreeListViewItem[1]");
1130+
IVisualElement<TreeListViewItem> item2 = await treeListView.GetElement<TreeListViewItem>("/TreeListViewItem[2]");
1131+
1132+
// add three children to the second item
1133+
await AddChildren(item2, 3, addButton);
1134+
1135+
// Expand the second item
1136+
await item2.LeftClickExpander();
1137+
await Task.Delay(50);
1138+
1139+
// select the second child
1140+
IVisualElement<TreeListViewItem> child2 = await treeListView.GetElement<TreeListViewItem>("/TreeListViewItem[4]");
1141+
await child2.LeftClick();
1142+
1143+
// Collapse the parent item
1144+
await item2.LeftClickExpander();
1145+
await Task.Delay(50);
1146+
1147+
// Left click on item 1, this should cause the previous selection to clear
1148+
await item1.LeftClick();
1149+
await Task.Delay(50);
1150+
1151+
await treeListView.RemoteExecute(AssertSelectedItems);
1152+
1153+
recorder.Success();
1154+
1155+
// Assert inside of the remote executed method because we can't return an IList, since it's not serializable
1156+
static void AssertSelectedItems(TreeListView treeListView)
1157+
{
1158+
var viewModel = (TreeListViewDataBinding)treeListView.DataContext;
1159+
1160+
Assert.Equal(["1"], viewModel.SelectedItems.Select(x => x.Value));
1161+
}
1162+
}
1163+
1164+
[Fact]
1165+
public async Task TreeListView_AddingDuplicateItemsAndSelectingWithArrowKeys_SelectsEachItemInTurn()
1166+
{
1167+
await using var recorder = new TestRecorder(App);
1168+
1169+
IVisualElement<Grid> root = (await LoadUserControl(typeof(TreeListViewDataBinding))).As<Grid>();
1170+
IVisualElement<TreeListView> treeListView = await root.GetElement<TreeListView>();
1171+
IVisualElement<Button> addDuplicateButton = await root.GetElement(ElementQuery.PropertyExpression<Button>(x => x.Content, "Add Duplicate"));
1172+
1173+
IVisualElement<TreeListViewItem> item1 = await treeListView.GetElement<TreeListViewItem>("/TreeListViewItem[1]");
1174+
1175+
// Left click on item 1 to select it
1176+
await item1.LeftClick();
1177+
await Task.Delay(50);
1178+
1179+
// Add two duplicates to the tree
1180+
await addDuplicateButton.LeftClick();
1181+
await Task.Delay(50);
1182+
1183+
await addDuplicateButton.LeftClick();
1184+
await Task.Delay(50);
1185+
1186+
IVisualElement<TreeListViewItem> item = await treeListView.GetElement<TreeListViewItem>($"/TreeListViewItem[0]");
1187+
await item.LeftClick();
1188+
await Task.Delay(50);
1189+
1190+
await treeListView.RemoteExecute(AssertSelectedItems, "0");
1191+
1192+
for(int i = 0; i < 2; i++)
1193+
{
1194+
// Press down arrow to select the next item
1195+
await treeListView.SendKeyboardInput($"{Key.Down}");
1196+
await Task.Delay(50);
1197+
await treeListView.RemoteExecute(AssertSelectedItems, "1");
1198+
}
1199+
1200+
await treeListView.SendKeyboardInput($"{Key.Down}");
1201+
await Task.Delay(50);
1202+
await treeListView.RemoteExecute(AssertSelectedItems, "2");
1203+
1204+
recorder.Success();
1205+
1206+
// Assert inside of the remote executed method because we can't return an IList, since it's not serializable
1207+
static void AssertSelectedItems(TreeListView treeListView, string expected)
1208+
{
1209+
var viewModel = (TreeListViewDataBinding)treeListView.DataContext;
1210+
1211+
Assert.Equal([expected], viewModel.SelectedItems.Select(x => x.Value));
1212+
}
1213+
}
1214+
1215+
11211216
private static async Task AssertTreeItemContent(IVisualElement<TreeListView> treeListView, int index, string content, bool isExpanded = false)
11221217
{
11231218
await Wait.For(async () =>

tests/MaterialDesignThemes.UITests/WPF/TreeListViews/TreeListViewWithCollectionView.xaml.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ namespace MaterialDesignThemes.UITests.WPF.TreeListViews;
99
/// </summary>
1010
public partial class TreeListViewWithCollectionView : UserControl
1111
{
12-
private ObservableCollection<TreeItem> ItemsSource { get; } = new();
12+
private ObservableCollection<TreeItem> ItemsSource { get; } = [];
1313

1414
public ICollectionView Items { get; }
1515

0 commit comments

Comments
 (0)