Skip to content

Commit

Permalink
Added FindFirstLevelDescendants[OrSelf] APIs
Browse files Browse the repository at this point in the history
  • Loading branch information
Sergio0694 committed Dec 20, 2021
1 parent c1625f2 commit 06517a6
Show file tree
Hide file tree
Showing 2 changed files with 135 additions and 0 deletions.
38 changes: 38 additions & 0 deletions Microsoft.Toolkit.Uwp.UI/Extensions/DependencyObjectExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,44 @@ static IEnumerable<DependencyObject> ThrowArgumentOutOfRangeExceptionForInvalidS
};
}

/// <summary>
/// Find all first level descendant elements of the specified element. This method can be chained
/// with INQ calls to add additional filters or projections on top of the returned results.
/// </summary>
/// <param name="element">The root element.</param>
/// <returns>All the first level descendant <see cref="DependencyObject"/> instance from <paramref name="element"/>.</returns>
public static IEnumerable<DependencyObject> FindFirstLevelDescendants(this DependencyObject element)
{
int childrenCount = VisualTreeHelper.GetChildrenCount(element);

for (var i = 0; i < childrenCount; i++)
{
DependencyObject child = VisualTreeHelper.GetChild(element, i);

yield return child;
}
}

/// <summary>
/// Find all first level descendant elements of the specified element. This method can be chained
/// with INQ calls to add additional filters or projections on top of the returned results.
/// </summary>
/// <param name="element">The root element.</param>
/// <returns>All the first level descendant <see cref="DependencyObject"/> instance from <paramref name="element"/>.</returns>
public static IEnumerable<DependencyObject> FindFirstLevelDescendantsOrSelf(this DependencyObject element)
{
yield return element;

int childrenCount = VisualTreeHelper.GetChildrenCount(element);

for (var i = 0; i < childrenCount; i++)
{
DependencyObject child = VisualTreeHelper.GetChild(element, i);

yield return child;
}
}

/// <summary>
/// Find all descendant elements of the specified element (or self). This method can be chained
/// with LINQ calls to add additional filters or projections on top of the returned results.
Expand Down
97 changes: 97 additions & 0 deletions UnitTests/UnitTests.UWP/Extensions/Test_VisualTreeExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,103 @@ await App.DispatcherQueue.EnqueueAsync(async () =>
});
}

[TestCategory("VisualTree")]
[TestMethod]
public async Task Test_VisualTree_FindFirstLevelDescendants_Exists()
{
await App.DispatcherQueue.EnqueueAsync(async () =>
{
var treeRoot = XamlReader.Load(@"<Page
xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""> <!-- Starting Point -->
<Grid>
<Border x:Name=""A""/>
<TextBlock x:Name=""B""/>
<StackPanel x:Name=""C"">
<TextBox/>
<TextBlock/>
</StackPanel>
<Grid x:Name=""D"">
<TextBlock/>
<StackPanel>
<TextBox/>
<TextBlock/>
</StackPanel>
<TextBlock/>
</Grid>
<TextBlock x:Name=""E""/>
</Grid>
</Page>") as Page;
// Test Setup
Assert.IsNotNull(treeRoot, "XAML Failed to Load");
// Initialize Visual Tree
await SetTestContentAsync(treeRoot);
// Main Test
var rootGrid = treeRoot.FindDescendant<Grid>();
var children = rootGrid.FindFirstLevelDescendants().ToArray();
Assert.AreEqual(5, children.Length, "Expected to find 5 children.");
Assert.IsTrue(children.Any(c => ((FrameworkElement)c).Name == "A"), "Couldn't find child 'A'");
Assert.IsTrue(children.Any(c => ((FrameworkElement)c).Name == "A"), "Couldn't find child 'B'");
Assert.IsTrue(children.Any(c => ((FrameworkElement)c).Name == "A"), "Couldn't find child 'C'");
Assert.IsTrue(children.Any(c => ((FrameworkElement)c).Name == "A"), "Couldn't find child 'D'");
Assert.IsTrue(children.Any(c => ((FrameworkElement)c).Name == "A"), "Couldn't find child 'E'");
});
}

[TestCategory("VisualTree")]
[TestMethod]
public async Task Test_VisualTree_FindFirstLevelDescendantsOrSelf_Exists()
{
await App.DispatcherQueue.EnqueueAsync(async () =>
{
var treeRoot = XamlReader.Load(@"<Page
xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""> <!-- Starting Point -->
<Grid x:Name=""RootGrid"">
<Border x:Name=""A""/>
<TextBlock x:Name=""B""/>
<StackPanel x:Name=""C"">
<TextBox/>
<TextBlock/>
</StackPanel>
<Grid x:Name=""D"">
<TextBlock/>
<StackPanel>
<TextBox/>
<TextBlock/>
</StackPanel>
<TextBlock/>
</Grid>
<TextBlock x:Name=""E""/>
</Grid>
</Page>") as Page;
// Test Setup
Assert.IsNotNull(treeRoot, "XAML Failed to Load");
// Initialize Visual Tree
await SetTestContentAsync(treeRoot);
// Main Test
var rootGrid = treeRoot.FindDescendant<Grid>();
var childrenOrSelf = rootGrid.FindFirstLevelDescendantsOrSelf().ToArray();
Assert.AreEqual(6, childrenOrSelf.Length, "Expected to find 6 children or self.");
Assert.IsTrue(childrenOrSelf.Any(c => ((FrameworkElement)c).Name == "RootGrid"), "Couldn't find self");
Assert.IsTrue(childrenOrSelf.Any(c => ((FrameworkElement)c).Name == "A"), "Couldn't find child 'A'");
Assert.IsTrue(childrenOrSelf.Any(c => ((FrameworkElement)c).Name == "A"), "Couldn't find child 'B'");
Assert.IsTrue(childrenOrSelf.Any(c => ((FrameworkElement)c).Name == "A"), "Couldn't find child 'C'");
Assert.IsTrue(childrenOrSelf.Any(c => ((FrameworkElement)c).Name == "A"), "Couldn't find child 'D'");
Assert.IsTrue(childrenOrSelf.Any(c => ((FrameworkElement)c).Name == "A"), "Couldn't find child 'E'");
});
}

[TestCategory("VisualTree")]
[TestMethod]
public async Task Test_VisualTree_FindAscendant_Exists()
Expand Down

0 comments on commit 06517a6

Please sign in to comment.