Skip to content

Commit 05ad5d1

Browse files
Add more test cases to try and track issue for #107
1 parent 6854bb9 commit 05ad5d1

File tree

2 files changed

+127
-2
lines changed

2 files changed

+127
-2
lines changed

components/Extensions/tests/Element/FrameworkElementExtensionsTests.RelativeAncestor.cs

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,128 @@ public void FrameworkElementExtension_RelativeAncestor_InDataTemplate(FrameworkE
2727

2828
Assert.AreEqual(3, count, "Didn't find three textblocks");
2929
}
30+
31+
[TestCategory("FrameworkElementExtension")]
32+
[UIThreadTestMethod]
33+
public async Task FrameworkElementExtension_RelativeAncestor_FreeParentBaseline(FrameworkElementRelativeAncestorDataTemplateTestPage page)
34+
{
35+
var text = page.FindDescendant<TextBox>();
36+
37+
Assert.IsNotNull(text, "Couldn't find TextBox");
38+
39+
// Grab a hold of a weak reference for TextBox so we can detect when it unloads.
40+
WeakReference textRef = new(text);
41+
text = null;
42+
43+
var parent = page.FindDescendant<Grid>();
44+
45+
Assert.IsNotNull(parent, "Couldn't find parent Grid");
46+
47+
// Remove all the children from the grid to simulate it unloading.
48+
VisualTreeHelper.DisconnectChildrenRecursive(parent);
49+
parent.Children.Clear();
50+
parent = null;
51+
52+
// Wait for the Visual Tree to perform removals and clean-up
53+
await CompositionTargetHelper.ExecuteAfterCompositionRenderingAsync(() => { });
54+
55+
// Wait for the .NET Garbage Collector to clean up references
56+
GC.Collect();
57+
GC.WaitForPendingFinalizers();
58+
59+
Assert.IsFalse(textRef.IsAlive, "TextBox is still alive...");
60+
}
61+
62+
[TestCategory("FrameworkElementExtension")]
63+
[UIThreadTestMethod]
64+
public async Task FrameworkElementExtension_RelativeAncestor_FreeParent(FrameworkElementRelativeAncestorDataTemplateTestPage page)
65+
{
66+
var list = page.FindDescendant<ListView>();
67+
68+
Assert.IsNotNull(list, "Couldn't find listview");
69+
70+
// Grab a hold of a weak reference for ListView so we can detect when it unloads.
71+
WeakReference listRef = new(list);
72+
list = null;
73+
74+
// Remove all the children from the grid to simulate it unloading.
75+
VisualTreeHelper.DisconnectChildrenRecursive(page);
76+
page.Content = null;
77+
78+
// Wait for the Visual Tree to perform removals and clean-up
79+
await CompositionTargetHelper.ExecuteAfterCompositionRenderingAsync(() => { });
80+
81+
// Wait for the .NET Garbage Collector to clean up references
82+
GC.Collect();
83+
GC.WaitForPendingFinalizers();
84+
85+
Assert.IsFalse(listRef.IsAlive, "ListView is still alive...");
86+
}
87+
88+
[TestCategory("FrameworkElementExtension")]
89+
[UIThreadTestMethod]
90+
public async Task FrameworkElementExtension_RelativeAncestor_FreePageNavigation()
91+
{
92+
TaskCompletionSource<bool?> taskCompletionSource = new();
93+
var frame = new Frame();
94+
frame.Navigated += OnNavigated;
95+
96+
await LoadTestContentAsync(frame);
97+
98+
// Navigate to the new page.
99+
frame.Navigate(typeof(FrameworkElementRelativeAncestorDataTemplateTestPage), null, new SuppressNavigationTransitionInfo());
100+
101+
async void OnNavigated(object sender, NavigationEventArgs e)
102+
{
103+
frame.Navigated -= OnNavigated;
104+
105+
// Wait for first Render pass
106+
await CompositionTargetHelper.ExecuteAfterCompositionRenderingAsync(() => { });
107+
108+
taskCompletionSource.SetResult(true);
109+
}
110+
111+
// Wait for frame to navigate/load
112+
var result = await taskCompletionSource.Task;
113+
Assert.IsTrue(result, "Navigation didn't complete");
114+
115+
// Find the ListView we want to track
116+
117+
var list = frame.FindDescendant<ListView>();
118+
119+
Assert.IsNotNull(list, "Couldn't find listview");
120+
121+
// Grab a hold of a weak reference for ListView so we can detect when it unloads.
122+
WeakReference listRef = new(list);
123+
list = null;
124+
125+
TaskCompletionSource<bool?> taskCompletionSource2 = new();
126+
frame.Navigated += OnNavigated2;
127+
128+
async void OnNavigated2(object sender, NavigationEventArgs e)
129+
{
130+
frame.Navigated -= OnNavigated2;
131+
132+
// Wait for first Render pass
133+
await CompositionTargetHelper.ExecuteAfterCompositionRenderingAsync(() => { });
134+
135+
taskCompletionSource2.SetResult(true);
136+
}
137+
138+
// Navigate to any other page to unload our other one
139+
frame.Navigate(typeof(BitmapIconExtensionTestPage), null, new SuppressNavigationTransitionInfo());
140+
141+
// Wait for navigation to complete
142+
result = await taskCompletionSource2.Task;
143+
Assert.IsTrue(result, "Navigation didn't complete 2");
144+
145+
// Wait for the Visual Tree to perform removals and clean-up
146+
await CompositionTargetHelper.ExecuteAfterCompositionRenderingAsync(() => { });
147+
148+
// Wait for the .NET Garbage Collector to clean up references
149+
GC.Collect();
150+
GC.WaitForPendingFinalizers();
151+
152+
Assert.IsFalse(listRef.IsAlive, "ListView is still alive...");
153+
}
30154
}

components/Extensions/tests/Element/FrameworkElementRelativeAncestorDataTemplateTestPage.xaml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@
88
mc:Ignorable="d">
99

1010
<Grid>
11-
<ListView x:Name="ListViewControl"
12-
Tag="Hello">
11+
<ListView Tag="Hello">
1312
<ListView.ItemTemplate>
1413
<DataTemplate>
1514
<TextBlock ui:FrameworkElementExtensions.AncestorType="ListView"
@@ -20,5 +19,7 @@
2019
<x:String>2</x:String>
2120
<x:String>3</x:String>
2221
</ListView>
22+
<!-- Another child to test clearing GC -->
23+
<TextBox />
2324
</Grid>
2425
</Page>

0 commit comments

Comments
 (0)