В чем разница визуального и логического дерева в WPF
Что проверяют
Понимаете ли вы, как WPF превращает XAML в то, что рисуется на экране, и почему у одного окна две иерархии. Следом обычно спрашивают, по какому дереву идут routed events и как добраться до элемента внутри шаблона.
Как отвечать
Логическое дерево это то, что вы написали в XAML: Window, в нём StackPanel, в ней Button и её Content. Визуальное дерево это то, что реально участвует в отрисовке: каждый контрол разворачивается по своему ControlTemplate, и Button превращается в Border, ContentPresenter и TextBlock.
- состав: в логическом дереве бывают и не визуальные объекты (строка в
Content), визуальное состоит только из наследниковVisualиVisual3D; - API:
LogicalTreeHelper.GetChildrenиGetParentдля логического,VisualTreeHelper.GetChild,GetChildrenCountиGetParentдля визуального; - что опирается на логическое: поиск ресурсов для
StaticResourceиDynamicResource,ElementNameв привязках, наследованиеDataContextиFontSize(сначала через логического родителя, при его отсутствии через визуального); - что опирается на визуальное: рендеринг, hit testing,
RelativeSourceсFindAncestor, маршрут routed events; - когда визуальное готово: шаблон применяется в
ApplyTemplate, поэтому в конструкторе визуальных детей ещё нет, искать их надо вOnApplyTemplateили послеLoaded.
Покажите практику: чтобы найти ScrollViewer внутри ListBox, пишут рекурсивный обход через VisualTreeHelper, а в своём контроле берут часть шаблона через GetTemplateChild. Смотреть дерево вживую удобно в Live Visual Tree в Visual Studio или в Snoop.
Где спотыкаются
Говорят, что события идут по логическому дереву. Bubbling и tunneling идут по визуальному, поэтому клик по TextBlock внутри шаблона кнопки доходит до самой кнопки.
Ищут элементы шаблона через VisualTreeHelper в конструкторе и получают ноль детей, потому что шаблон ещё не применён.
Не знают, что ContextMenu и Popup живут в собственном визуальном дереве. Привязки внутри меню теряют DataContext окна, и их чинят через PlacementTarget.DataContext.