4

I have tried finding an answer to this problem and in every post I find there is an answer to finding children recursively but none of them work with hidden or collapsed children

Also in every post someone has asked if this is possible but no one has answered so I am beginning to think this isn't possible

If anyone has a way of doing this I will be eternally grateful.

My function looks like this:

        public static DependencyObject FindLogicalDescendentByName(this DependencyObject source, string name)
    {
        DependencyObject result = null;
        IEnumerable children = LogicalTreeHelper.GetChildren(source);

        foreach (var child in children)
        {
            if (child is DependencyObject)
            {
                if (child is FrameworkElement)
                {
                    if ((child as FrameworkElement).Name.Equals(name))
                        result = (DependencyObject)child;
                    else
                        result = (child as DependencyObject).FindLogicalDescendentByName(name);
                }
                else
                {
                    result = (child as DependencyObject).FindLogicalDescendentByName(name);
                }
                if (result != null)
                    return result;
            }
        }
        return result;
    }

-EDITED So, I realise my problem is that I was trying to find the item before it was created,

I was binding to a property in xaml that would go off and find an item by a given name, but the item wasnt created at that point in time, if I re-ordered the item in xaml, it works and the item is found... doh!

Kezza
  • 736
  • 9
  • 25

1 Answers1

3

Here is my code, it works if you specify the X:Name and the type

Example of the call:

System.Windows.Controls.Image myImage = FindChild<System.Windows.Controls.Image>(this (or parent), "ImageName");



/// <summary>
/// Find specific child (name and type) from parent
/// </summary>
public static T FindChild<T>(DependencyObject parent, string childName) where T : DependencyObject
{
   // Confirm parent and childName are valid. 
   if (parent == null) return null;

   T foundChild = null;

   int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
   for (int i = 0; i < childrenCount; i++)
   {
      var child = VisualTreeHelper.GetChild(parent, i);
      // If the child is not of the request child type child
      T childType = child as T;
      if (childType == null)
      {
         // recursively drill down the tree
         foundChild = FindChild<T>(child, childName);

         // If the child is found, break so we do not overwrite the found child. 
         if (foundChild != null) break;
      }
      else if (!string.IsNullOrEmpty(childName))
      {
         var frameworkElement = child as FrameworkElement;
         // If the child's name is set for search
         if (frameworkElement != null && frameworkElement.Name == childName)
         {
            // if the child's name is of the request name
            foundChild = (T)child;
            break;
         }
      }
      else
      {
         // child element found.
         foundChild = (T)child;
         break;
      }
   }

     return foundChild;
  }
mlemay
  • 1,622
  • 2
  • 32
  • 53
  • 1
    This still doesn't seem to work, I have 2 possible spanners to throw in. 1. my controls are in a 3rd party panel that doesn't seem to have any visual tree elements but has logical tree elements, hence using the logical tree. 2. 3rd party panel and all controls inside are in a resource dictionary, and being used as a template. – Kezza May 23 '12 at 15:56
  • So I added a little stack panel around the two controls that I wanted to be found and I have stepped through your code and when I get to the stack panel and the childrenCount is returned from the VisualTreeHelper it's value is 1, this is the control that is visible, the control that is not visible is still missing... they are of the same type and both have the x:Name attribute set – Kezza May 23 '12 at 16:05
  • 1
    I figured out what I was doing wrong. thanks for your response though – Kezza May 23 '12 at 16:23