Skip to content

Commit 06517a6

Browse files
committed
Added FindFirstLevelDescendants[OrSelf] APIs
1 parent c1625f2 commit 06517a6

File tree

2 files changed

+135
-0
lines changed

2 files changed

+135
-0
lines changed

Microsoft.Toolkit.Uwp.UI/Extensions/DependencyObjectExtensions.cs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,44 @@ static IEnumerable<DependencyObject> ThrowArgumentOutOfRangeExceptionForInvalidS
543543
};
544544
}
545545

546+
/// <summary>
547+
/// Find all first level descendant elements of the specified element. This method can be chained
548+
/// with INQ calls to add additional filters or projections on top of the returned results.
549+
/// </summary>
550+
/// <param name="element">The root element.</param>
551+
/// <returns>All the first level descendant <see cref="DependencyObject"/> instance from <paramref name="element"/>.</returns>
552+
public static IEnumerable<DependencyObject> FindFirstLevelDescendants(this DependencyObject element)
553+
{
554+
int childrenCount = VisualTreeHelper.GetChildrenCount(element);
555+
556+
for (var i = 0; i < childrenCount; i++)
557+
{
558+
DependencyObject child = VisualTreeHelper.GetChild(element, i);
559+
560+
yield return child;
561+
}
562+
}
563+
564+
/// <summary>
565+
/// Find all first level descendant elements of the specified element. This method can be chained
566+
/// with INQ calls to add additional filters or projections on top of the returned results.
567+
/// </summary>
568+
/// <param name="element">The root element.</param>
569+
/// <returns>All the first level descendant <see cref="DependencyObject"/> instance from <paramref name="element"/>.</returns>
570+
public static IEnumerable<DependencyObject> FindFirstLevelDescendantsOrSelf(this DependencyObject element)
571+
{
572+
yield return element;
573+
574+
int childrenCount = VisualTreeHelper.GetChildrenCount(element);
575+
576+
for (var i = 0; i < childrenCount; i++)
577+
{
578+
DependencyObject child = VisualTreeHelper.GetChild(element, i);
579+
580+
yield return child;
581+
}
582+
}
583+
546584
/// <summary>
547585
/// Find all descendant elements of the specified element (or self). This method can be chained
548586
/// with LINQ calls to add additional filters or projections on top of the returned results.

UnitTests/UnitTests.UWP/Extensions/Test_VisualTreeExtensions.cs

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,103 @@ await App.DispatcherQueue.EnqueueAsync(async () =>
439439
});
440440
}
441441

442+
[TestCategory("VisualTree")]
443+
[TestMethod]
444+
public async Task Test_VisualTree_FindFirstLevelDescendants_Exists()
445+
{
446+
await App.DispatcherQueue.EnqueueAsync(async () =>
447+
{
448+
var treeRoot = XamlReader.Load(@"<Page
449+
xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
450+
xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""> <!-- Starting Point -->
451+
<Grid>
452+
<Border x:Name=""A""/>
453+
<TextBlock x:Name=""B""/>
454+
<StackPanel x:Name=""C"">
455+
<TextBox/>
456+
<TextBlock/>
457+
</StackPanel>
458+
<Grid x:Name=""D"">
459+
<TextBlock/>
460+
<StackPanel>
461+
<TextBox/>
462+
<TextBlock/>
463+
</StackPanel>
464+
<TextBlock/>
465+
</Grid>
466+
<TextBlock x:Name=""E""/>
467+
</Grid>
468+
</Page>") as Page;
469+
470+
// Test Setup
471+
Assert.IsNotNull(treeRoot, "XAML Failed to Load");
472+
473+
// Initialize Visual Tree
474+
await SetTestContentAsync(treeRoot);
475+
476+
// Main Test
477+
var rootGrid = treeRoot.FindDescendant<Grid>();
478+
var children = rootGrid.FindFirstLevelDescendants().ToArray();
479+
480+
Assert.AreEqual(5, children.Length, "Expected to find 5 children.");
481+
482+
Assert.IsTrue(children.Any(c => ((FrameworkElement)c).Name == "A"), "Couldn't find child 'A'");
483+
Assert.IsTrue(children.Any(c => ((FrameworkElement)c).Name == "A"), "Couldn't find child 'B'");
484+
Assert.IsTrue(children.Any(c => ((FrameworkElement)c).Name == "A"), "Couldn't find child 'C'");
485+
Assert.IsTrue(children.Any(c => ((FrameworkElement)c).Name == "A"), "Couldn't find child 'D'");
486+
Assert.IsTrue(children.Any(c => ((FrameworkElement)c).Name == "A"), "Couldn't find child 'E'");
487+
});
488+
}
489+
490+
[TestCategory("VisualTree")]
491+
[TestMethod]
492+
public async Task Test_VisualTree_FindFirstLevelDescendantsOrSelf_Exists()
493+
{
494+
await App.DispatcherQueue.EnqueueAsync(async () =>
495+
{
496+
var treeRoot = XamlReader.Load(@"<Page
497+
xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
498+
xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""> <!-- Starting Point -->
499+
<Grid x:Name=""RootGrid"">
500+
<Border x:Name=""A""/>
501+
<TextBlock x:Name=""B""/>
502+
<StackPanel x:Name=""C"">
503+
<TextBox/>
504+
<TextBlock/>
505+
</StackPanel>
506+
<Grid x:Name=""D"">
507+
<TextBlock/>
508+
<StackPanel>
509+
<TextBox/>
510+
<TextBlock/>
511+
</StackPanel>
512+
<TextBlock/>
513+
</Grid>
514+
<TextBlock x:Name=""E""/>
515+
</Grid>
516+
</Page>") as Page;
517+
518+
// Test Setup
519+
Assert.IsNotNull(treeRoot, "XAML Failed to Load");
520+
521+
// Initialize Visual Tree
522+
await SetTestContentAsync(treeRoot);
523+
524+
// Main Test
525+
var rootGrid = treeRoot.FindDescendant<Grid>();
526+
var childrenOrSelf = rootGrid.FindFirstLevelDescendantsOrSelf().ToArray();
527+
528+
Assert.AreEqual(6, childrenOrSelf.Length, "Expected to find 6 children or self.");
529+
530+
Assert.IsTrue(childrenOrSelf.Any(c => ((FrameworkElement)c).Name == "RootGrid"), "Couldn't find self");
531+
Assert.IsTrue(childrenOrSelf.Any(c => ((FrameworkElement)c).Name == "A"), "Couldn't find child 'A'");
532+
Assert.IsTrue(childrenOrSelf.Any(c => ((FrameworkElement)c).Name == "A"), "Couldn't find child 'B'");
533+
Assert.IsTrue(childrenOrSelf.Any(c => ((FrameworkElement)c).Name == "A"), "Couldn't find child 'C'");
534+
Assert.IsTrue(childrenOrSelf.Any(c => ((FrameworkElement)c).Name == "A"), "Couldn't find child 'D'");
535+
Assert.IsTrue(childrenOrSelf.Any(c => ((FrameworkElement)c).Name == "A"), "Couldn't find child 'E'");
536+
});
537+
}
538+
442539
[TestCategory("VisualTree")]
443540
[TestMethod]
444541
public async Task Test_VisualTree_FindAscendant_Exists()

0 commit comments

Comments
 (0)