Найти предка элемента управления по типу
У меня есть UserControl
"ребенок" внутри другого UserControl
(это действует как TabItem в TabControl
). Между ребенком UserControl
и предок TabItem - это ряд других элементов управления (например: Grid
с, а StackPanel
возможно ScrollViewer
, так далее).
Я хочу получить доступ к свойству TabItem UserControl
в моем ребенке UserControl
и настроил обычно предлагаемую рекурсивную функцию, которая проходит по дереву Visual. Однако это всегда возвращалось true
при первой нулевой проверке, пока я не добавил запрос в логическое дерево.
Код:
public MyTabItem FindParentTabItem(DependencyObject child)
{
DependencyObject parent = VisualTreeHelper.GetParent(child) ?? LogicalTreeHelper.GetParent(child);
// are we at the top of the tree
if (parent == null)
{
return null;
}
MyTabItem parentTabItem = parent as MyTabItem;
if (parentTabItem != null)
{
return parentTabItem;
}
else
{
//use recursion until it reaches the control
return FindParentTabItem(parent);
}
}
К сожалению, это тоже возвращает ноль. При переходе по методу я вижу, что он находит правильный UserControl
TabItem, но затем, когда он возвращает (?) Обратно через возвраты, он возвращает это обратно к нулю, который затем возвращается вызывающему методу (в дочернем элементе). UserControl
Загруженное событие):
MyTabItem tab = FindParentTabItem(this);
Как это исправить, чтобы мой метод правильно возвращал найденное MyTabItem
?
1 ответ
Вот рабочее решение, протестированное модулем.
public static T FindAncestor<T>(DependencyObject obj)
where T : DependencyObject
{
if (obj != null)
{
var dependObj = obj;
do
{
dependObj = GetParent(dependObj);
if (dependObj is T)
return dependObj as T;
}
while (dependObj != null);
}
return null;
}
public static DependencyObject GetParent(DependencyObject obj)
{
if (obj == null)
return null;
if (obj is ContentElement)
{
var parent = ContentOperations.GetParent(obj as ContentElement);
if (parent != null)
return parent;
if (obj is FrameworkContentElement)
return (obj as FrameworkContentElement).Parent;
return null;
}
return VisualTreeHelper.GetParent(obj);
}
Использование будет
FindAncestor<MyTabItemType>(someChild);
Редактировать:
Давайте предположим, что ваш xaml выглядит так, как вы его описываете:
<UserControl>
<Grid></Grid>
<StackPanel></StackPanel>
<!-- Probably also something around your child -->
<Grid>
<UserControl x:Name="child"/>
</Grid>
</UserControl>
Вы в настоящее время в вашем child-xaml.cs
void OnChildUserControlLoaded(object sender, RoutedEventArgs e)
{
var parent = FindAncestor<ParentUserControlType>(this);
DoSomething(parent.SomeProperty);
}
Если вы не сделаете что-то, что вы не описали, код будет работать как есть.
Я предлагаю вам предоставить MCVE всю необходимую информацию.