#wpf #z-index #z-order
#wpf #z-индекс #z-порядок
Вопрос:
У меня есть список с панелью элементов Canvas, которая отображает 2 разных типа объектов: NodeVMs и LinkLineVMs (с использованием CompositeCollection). Каждый объект виртуальной машины имеет DataTemplate:
DataTemplate NodeVMs имеет TextBlock
(A)
LinkLineVMs DataTemplate имеет Line
(B) и TextBlock
(C) Как получить следующий абсолютный z-порядок: A (вверху), C, B (внизу).
<ListBox>
<ListBox.Resources>
<DataTemplate DataType="{x:Type p:NodeVM}">
<StackPanel>
<TextBlock ... />
...
</StackPanel>
</DataTemplate>
<DataTemplate DataType="{x:Type p:NetworkLinkVM}">
<Grid>
<Line ... />
<TextBlock ... />
</Grid>
</DataTemplate>
</ListBox.Resources>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<Canvas IsItemsHost="True" PreviewMouseUp="network_visualization_list_PreviewMouseUp" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox>
Кто-то однажды сказал, что картинка стоит 1000 слов. Зеленый прямоугольник == NodeVM, строка маленький прямоугольник == NetworkLink vm. A в порядке, так как ссылка [-30] проходит по другой ссылке, НО B является проблемой, так как поле ссылка [-31] скрыто ПОД ссылкой [-32]
Ответ №1:
Установите свой индекс zIndex ListBox.ItemContainerStyle
вместо вашего DataTemplate.
Причина этого в том, что все элементы заключены в a ListBoxItem
, поэтому вам нужно установить zIndex на ListBoxItem
вместо на DataTemplate
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Canvas.ZIndex"
Value="{Binding Converter={StaticResource GetObjectZIndexConverter}}" />
</Style>
Вам понадобится конвертер, который проверяет typeof
ваш объект, связанный с данными, и возвращает правильный zIndex на основе, если это NodeVM
или NetworkLinkVM
.
Это установит только zIndex для ваших DataTemplates, но как только они будут отсортированы, вы можете установить zIndex NetworkLinkVM's
для внутренних Line
и TextBlock
Комментарии:
1. Спасибо за информацию — я подумал, что ваше решение было хорошим, но, к сожалению, проблема все еще существует. Я опубликовал изображение, которое помогает лучше объяснить ситуацию. Я установил ваш конвертер, который помещает все узлы (зеленые) поверх — это хорошо. Но по-прежнему существует проблема с порядком элементов в списке, влияющим на zorder. Хотя в DataTemplate поле ссылки находится над строкой ссылки, строка поле позже в списке по-прежнему находится над полем из строки ранее в списке. Любые идеи приветствуются!
2. @Ricibob Hrrm Я понимаю, о чем ты говоришь. Есть ли шанс, что вы могли бы разделить свои линейные объекты на другой слой, чтобы все 3 ваших объекта (зеленые прямоугольники, синие прямоугольники и линии) существовали в одной коллекции, вместо того, чтобы синие прямоугольники и линии разделяли место в коллекции?
3. Да, это возможное решение, но, к сожалению, не очень практично. Коллекции представляют собой узлы и ссылки — это просто приведет к беспорядку, чтобы разорвать сильные стороны ссылок (блоки) из NetworkLinksVM только для z-порядка. Я думаю, что возможно чистое решение — просто нужно его найти!!
4. @Ricibob Вы могли бы попробовать поместить две версии ListBox друг на друга, при этом нижняя версия будет рисовать только линии, а верхняя версия будет рисовать только поля.
5. Что мне нужно, так это установить холст. zIndex для каждого элемента DataTemplate. Как получить доступ к холсту ItemsPanel из DataTemplate ListBoxItems? Здесь уже поздно — я подумаю об этом в выходные. Спасибо за вашу помощь.