Подтвердить что ты не робот

Почему свойство Parent контейнера элемента ItemsControl возвращает null, а не панель, на которой он сидит?

У меня есть я в тупике. У нас есть пользовательский элемент ItemsControl, который использует как пользовательские контейнеры, так и пользовательскую панель в качестве ItemsHost. Теперь панель имеет некоторые показатели, необходимые контейнерам для целей рендеринга. Поскольку они являются прямыми дочерними элементами панели в визуальном дереве, вы можете подумать, что свойство Parent контейнера вернет панель, но это не так!

Я также подтвердил эту точную вещь, используя Snoop на стандартном ListBox, поэтому это не является исключением для нашего кода, но, видимо, все контейнеры ItemsControls.

Теперь я знаю, что я могу использовать VisualTreeHelper для получения визуального родителя (это то, что мне нужно), но почему родительский элемент не был панелью?

Если аргумент состоит в том, что панель является просто частью визуального дерева, а родитель зарезервирован для логического дерева, то разве родительский элемент не был бы ItemControl?

Если аргумент есть контейнер, также является частью визуального дерева ItemsControl, а не логическим деревом, то почему содержимое, помеченное в контейнере, возвращает контейнер в качестве свойства родителя?

Это означает, что если вы идете по логическому дереву из элемента данных, вы останавливаетесь в контейнерах, что может объяснить, почему наши привязки из контейнеров к панелям не работают должным образом. (Я считаю, что привязки основаны на логической иерархии, а не на визуальной, но я должен был бы проверить, чтобы убедиться.)

4b9b3361

Ответ 1

Я никогда не замечал этого, и это вызывало мое любопытство. После поиска подсказок в .NET Framework в том, что свойство Parent, похоже, действительно установлено вручную: Это потребовало нескольких шагов, но я обнаружил, что единственный способ изменить родительское свойство - вызвать эти методы:

parent affectation

Если я проанализирую, например, метод FrameworkElement.AddLogicalChild, я обнаружил, что эти методы используют его:

FrameworkElement.AddLogicalChild analysis

Это подтверждает, что родительское свойство должно ссылаться на логическое дерево. Я попытался создать собственный пользовательский элемент управления:

    [ContentProperty("CustomContent")]
public class CustomControl1 : Control
{
    static CustomControl1()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomControl1), new FrameworkPropertyMetadata(typeof(CustomControl1)));
    }

    public object CustomContent
    {
        get { return GetValue(CustomContentProperty); }
        set { SetValue(CustomContentProperty, value); }
    }

    public static readonly DependencyProperty CustomContentProperty = DependencyProperty.Register("CustomContent", typeof(object), typeof(CustomControl1));
}

с этим шаблоном:

<ControlTemplate TargetType="{x:Type local:CustomControl1}">
     <ContentPresenter ContentSource="CustomContent" />
</ControlTemplate>

Я использовал его следующим образом:

    <WpfApplication1:CustomControl1 Width="50" Height="50">
        <Rectangle Fill="Red" />
    </WpfApplication1:CustomControl1>

... это сработало так (например, шарм: -)):

custom control screen caprute

... и угадайте, что... Родитель прямоугольника не установлен: -)

У меня нет времени для продолжения расследования, но в отношении ItemsControl я полагаю, что, возможно, ItemContainerGenerator не знает логического родителя, в который он вставляет itemsContainers, который мог бы объяснить, почему родительское свойство не установлено в этом случае... но это нужно доказать...