Абсолютный z-порядок (для нескольких таблиц данных)

#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? Здесь уже поздно — я подумаю об этом в выходные. Спасибо за вашу помощь.