2
\$\begingroup\$

I created an helper method to return a List of UIElements where the returned elements have to match with one of the Types which I pass to the method.

First I used this method to get all the children of one type:

public static IEnumerable<T> FindVisualChildren<T>(DependencyObject dependencyObj) where T : DependencyObject
{
 if (dependencyObj != null)
 {
 for (int i = 0; i < VisualTreeHelper.GetChildrenCount(dependencyObj); i++)
 {
 DependencyObject child = VisualTreeHelper.GetChild(dependencyObj, i);
 if (child != null && child is T)
 {
 yield return (T)child;
 }
 foreach (T childOfChild in FindVisualChildren<T>(child))
 {
 yield return childOfChild;
 }
 }
 }
}

I called this method like:

var textBoxes = UIHelper.FindVisualChildren<TextBox>(currentView);

But I need to find find elements of multiple types, so I rewrote the helper method to accept a List of Types.

public static IEnumerable<UIElement> FindVisualChildrenOfMultipleTypes(List<Type> types, DependencyObject dependencyObj)
{
 if (dependencyObj != null)
 {
 for (int i = 0; i < VisualTreeHelper.GetChildrenCount(dependencyObj); i++)
 {
 DependencyObject child = VisualTreeHelper.GetChild(dependencyObj, i);
 if (child != null && types.Contains(child.GetType()))
 {
 yield return child as UIElement;
 }
 foreach (var childOfChild in FindVisualChildrenOfMultipleTypes(types, child))
 {
 yield return childOfChild;
 }
 }
 }
}

Called like:

List<Type> types= new List<Type>()
{
 typeof(CheckBox),
 typeof(RadioButton),
 typeof(TextBox)
};
var children = UIHelper.FindVisualChildrenOfMultipleTypes(types, currentView);

This works, but I think there a some improvements possible. For example the signature of my method, I think Generics can be used in the method signature, but I'm not very experienced with Generics, so advice on this would be nice. I'm also wondering if the performance of the method can be improved.

asked Mar 25, 2016 at 7:42
\$\endgroup\$
2
  • \$\begingroup\$ Neither of those are actually extension methods (in the C# sense), by the way. They are just static utility or helper methods. Add the this keyword to the front of the first parameter, and then they are extension methods. \$\endgroup\$ Commented Mar 25, 2016 at 13:38
  • \$\begingroup\$ @JesseC.Slicer I edited my post with the correct naming. Any advice on how to improve the performance or how to improve the method signature (except what you already told about it)?. \$\endgroup\$ Commented Mar 25, 2016 at 14:06

1 Answer 1

1
\$\begingroup\$

SRP

Your current soulution violates the Single Responsibility Principle because it does two things:

  • it enumerates all children and
  • it checks if a child is of the specified type

This can and should be splitted into two methods that you can implements as extensions.

The Children extension will only know how to get all children, nothing more. This means I removed the type checking and I reduced nesting by inverting the first condition.

public static IEnumerable<UIElement> Children(this DependencyObject dependencyObj)
{
 if (dependencyObj == null)
 {
 yield break;
 }
 for (int i = 0; i < VisualTreeHelper.GetChildrenCount(dependencyObj); i++)
 {
 var child = VisualTreeHelper.GetChild(dependencyObj, i);
 if (child != null)
 {
 yield return child as UIElement;
 }
 foreach (var childOfChild in child.Children())
 {
 yield return childOfChild;
 }
 }
}

The second extension OfTypes will be your filter. Here I changed the order of the parameters and decorated the last one with params which will allow you to easier specify the types without having to create an extra list for them.

public static IEnumerable<UIElement> OfTypes(this IEnumerable<UIElement> uiElements, params Type[] types)
{
 return uiElements.Where(x => types.Contains(x.GetType())); 
}

Example:

var result = currentView.Children().OfTypes(
 typeof(CheckBox),
 typeof(RadioButton),
 typeof(TextBox)
);

The separation of those two concerns allows you to reuse the Children extension for other purposes should you need it somewhere else.

FindVisualChildrenOfMultipleTypes

By using extensions like the two I've just suggested, you can get rid of the very long method name because you splitted it in multiple parts.

Heslacher
50.9k5 gold badges83 silver badges177 bronze badges
answered Oct 7, 2016 at 9:41
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.