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?
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
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
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With