查找控件的直接祖先/父级

时间:2012-04-26 15:27:40

标签: c# wpf user-controls casting parent-child

我有一个名为UserControl的{​​{1}},其中包含一个AddressTemplate,其中包含各种StackPanel& Labels。我需要的是找到Textboxes中某个控件的直接祖先/父级的方法。从本质上讲,我需要一种方法来确定给定AddressTemplate是否在Textbox内,或者在AddressTemplate之外,并且只是一个独立的控件。

到目前为止,我想出的是:

UserControl

问题是,我不断收到InvalidCastException,因为它无法将StackPanel强制转换为Control。有没有人知道正确的演员,或者解决这个问题的可行方法?

2 个答案:

答案 0 :(得分:6)

你可能想在这里使用LogicalTreeHelper.GetParent,它返回一个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;
 }

这将向上走逻辑父树,直到找不到您要查找的父级或用户控件。有关详细信息,请查看MSDN上的Trees in Wpf

答案 1 :(得分:2)

我使用下面的扩展方法,通过在可视树上走来创建所有视觉父母的IEnumerable

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;
}

这非常灵活。在您的示例中,您可以按如下方式使用它:

if (target.VisualParents().OfType<AddressTemplate>().Any()) {
     //the target is in the address template
}