Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find Immediate Ancestor/Parent of a control

I have a UserControl named AddressTemplate, which contains a StackPanel with an assortment of Labels & Textboxes. What I need is a way to find the immediate ancestor/parent of one of the controls within the AddressTemplate. Essentially, I need a way to determine whether a given Textbox is inside the AddressTemplate, or instead is outside this UserControl and is just a standalone control.

What I've come up with so far is this:

private bool FindParent(Control target)
    {
        Control currentParent = new Control();

        if (currentParent.GetType() == typeof(Window))
        {

        }
        else if (currentParent.GetType() != typeof(AddressTemplate) && currentParent.GetType() != null)
        {
            currentParent = (Control)target.Parent;
        }
        else
        {
            return true;
        }

        return false;            
    }

The problem is, I keep getting an InvalidCastException because it can't cast a StackPanel as a Control. Does anybody know the proper cast, or a viable way to fix this?

like image 325
Keven M Avatar asked Jan 17 '23 20:01

Keven M


2 Answers

You probably want to use LogicalTreeHelper.GetParent here, which returns a DependencyObject:

//- warning, coded in the SO editor window
private bool IsInAddressTemplate(DependencyObject target)
{
    DependencyObject current = target;
    Type targetType = typeof(AddressTemplate);

    while( current != null)
    {
       if( current.GetType() == targetType)
       {
          return true;
       }
       current = LogicalTreeHelper.GetParent(current);
    }
    return false;
 }

This would walk up the logical parent tree until it found no parent or the user control you are looking for. For more info, look at Trees in Wpf on MSDN

like image 161
Philip Rieck Avatar answered Jan 29 '23 14:01

Philip Rieck


I use the extension method below, which creates an IEnumerable of all of the visual parents by walking up the visual tree:

public static IEnumerable<DependencyObject> VisualParents(this DependencyObject element)
{
    element.ThrowIfNull("element");
    var parent = GetParent(element);

    while (parent != null)
    {
        yield return parent;
        parent = GetParent(parent);
    }
}

private static DependencyObject GetParent(DependencyObject element)
{
    var parent = VisualTreeHelper.GetParent(element);

        if (parent == null && element is FrameworkElement)
            parent = ((FrameworkElement)element).Parent;

    return parent;
}

This is then pretty flexible. In your example, you could use it as below:

if (target.VisualParents().OfType<AddressTemplate>().Any()) {
     //the target is in the address template
}
like image 32
Steve Greatrex Avatar answered Jan 29 '23 14:01

Steve Greatrex