Найти предка элемента управления по типу - PullRequest
0 голосов
/ 08 ноября 2018

У меня есть UserControl дочерний элемент в другом UserControl (он действует как TabItem в TabControl). Между дочерним элементом UserControl и предком TabItem находится ряд других элементов управления (например: Grid s, StackPanel, возможно ScrollViewer и т. Д.).

Я хочу получить доступ к свойству TabItem UserControl в моем дочернем элементе UserControl и настроить обычно предложенную рекурсивную функцию, которая проходит по дереву визуалов. Однако это всегда возвращало 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, но затем, когда он рекурсивно (?) Возвращается через возвращаемые значения, он возвращает это значение в ноль, которое затем возвращается вызывающему методу (в дочернем элементе *). Загруженное событие 1023 *):

MyTabItem tab = FindParentTabItem(this);

Как это исправить, чтобы мой метод правильно возвращал найденное MyTabItem?

1 Ответ

0 голосов
/ 08 ноября 2018

Вот рабочее модульное решение .

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

Edit:

Давайте предположим, что ваш 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 всю необходимую информацию.

...