Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Fix bug in GetChild method and add FindChild and FindParent #101

Merged
merged 1 commit into from
Feb 7, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 60 additions & 16 deletions src/Atc.Wpf/Helpers/VisualTreeHelperEx.cs
Original file line number Diff line number Diff line change
@@ -1,37 +1,81 @@
#pragma warning disable CS0162 // Unreachable code detected
namespace Atc.Wpf.Helpers;

/// <summary>
/// Provides extended methods for working with the visual tree in WPF applications.
/// </summary>
[SuppressMessage("Naming", "CA1711:Identifiers should not have incorrect suffix", Justification = "OK.")]
public static class VisualTreeHelperEx
{
public static T? GetParent<T>(DependencyObject child)
/// <summary>
/// Finds and returns the first parent object of the specified type T in the visual tree.
/// </summary>
/// <typeparam name="T">The type of the parent to find.</typeparam>
/// <param name="control">The starting dependency object to search up from.</param>
/// <returns>The first parent object of type T found in the visual tree, or null if no such parent exists.</returns>
public static T? GetParent<T>(
DependencyObject control)
where T : DependencyObject
{
var parent = VisualTreeHelper.GetParent(child);
=> FindParent<T>(control);

/// <summary>
/// Searches for and returns the first child object of the specified type T within the visual tree.
/// </summary>
/// <typeparam name="T">The type of the child to find.</typeparam>
/// <param name="control">The parent dependency object to search down from.</param>
/// <returns>The first child of type T found within the visual tree, or null if no such child exists.</returns>
public static T? GetChild<T>(
DependencyObject control)
where T : DependencyObject
=> FindChild<T>(control);

return parent switch
/// <summary>
/// Recursively finds the first parent of the specified type T in the visual tree.
/// </summary>
/// <typeparam name="T">The type of the parent to find.</typeparam>
/// <param name="control">The starting point dependency object to search up from.</param>
/// <returns>The first parent object of type T in the visual tree, or null if no such parent is found.</returns>
public static T? FindParent<T>(
DependencyObject control)
where T : DependencyObject
{
var parent = VisualTreeHelper.GetParent(control);
while (parent is not null)
{
null => null,
T tParent => tParent,
_ => GetParent<T>(parent),
};
if (parent is T tParent)
{
return tParent;
}

parent = VisualTreeHelper.GetParent(parent);
}

return null;
}

[SuppressMessage("Major Bug", "S1751:Loops with at most one iteration should be refactored", Justification = "OK.")]
public static T? GetChild<T>(DependencyObject control)
/// <summary>
/// Recursively searches for and returns the first child of the specified type T within the visual tree.
/// </summary>
/// <typeparam name="T">The type of the child to find.</typeparam>
/// <param name="control">The parent dependency object to search down from.</param>
/// <returns>The first child of type T, or null if no such child is found.</returns>
public static T? FindChild<T>(
DependencyObject control)
where T : DependencyObject
{
var childNumber = VisualTreeHelper.GetChildrenCount(control);
for (var i = 0; i < childNumber; i++)
{
var child = VisualTreeHelper.GetChild(control, i);
if (child is T tChild)
{
return tChild;
}

return child switch
var result = FindChild<T>(child);
if (result is not null)
{
null => null,
T tChild => tChild,
_ => GetChild<T>(child),
};
return result;
}
}

return null;
Expand Down
Loading