WPF Listbox Virtualization создает DisconnectedItems

Я пытаюсь создать элемент управления Graph, используя WPF ListBox. Я создал свой собственный Canvas, созданный на основе VirtualizingPanel, и сам занимаюсь реализацией и виртуализацией элементов.

Панель элементов списка затем устанавливается в качестве моего настраиваемого виртуализированного холста.

Проблема, с которой я сталкиваюсь, возникает в следующем сценарии:

Элемент ListBox A создается первым.Элемент ListBox B создается справа от элемента A на холсте.Элемент ListBox A виртуализируется первым (путем панорамирования его вне поля зрения).Элемент ListBox B виртуализируется вторым (снова путем панорамирования его вне поля зрения).Приведите ListBox Item A и B в поле зрения (т.е. реализуйте их)Используя Snoop, я обнаружил, что ListBox теперь имеет 3 элемента, один из которых представляет собой «DisconnectedItem», расположенный непосредственно под элементом ListBox B.

Что вызывает создание этого "DisconnectedItem"? Если бы я сначала виртуализировал B, а затем A, этот элемент не был бы создан. Моя теория заключается в том, что виртуализация элементов, которые предшествуют другим элементам в ListBox, приводит к отключению детей.

Проблема становится еще более очевидной при использовании графа с сотнями узлов, так как я в итоге получаю сотни отключенных элементов, пока я перемещаюсь.

Вот часть кода для холста:

/// <summary>
/// Arranges and virtualizes child element positionned explicitly.
/// </summary>
public class VirtualizingCanvas : VirtualizingPanel
{
   (...)

    protected override Size MeasureOverride(Size constraint)
    {
        ItemsControl itemsOwner = ItemsControl.GetItemsOwner(this);

        // For some reason you have to "touch" the children collection in 
        // order for the ItemContainerGenerator to initialize properly.
        var necessaryChidrenTouch = Children;

        IItemContainerGenerator generator = ItemContainerGenerator;

        IDisposable generationAction = null;

        int index = 0;
        Rect visibilityRect = new Rect(
            -HorizontalOffset / ZoomFactor,
            -VerticalOffset / ZoomFactor,
            ActualWidth / ZoomFactor,
            ActualHeight / ZoomFactor);

        // Loop thru the list of items and generate their container
        // if they are included in the current visible view.
        foreach (object item in itemsOwner.Items)
        {
            var virtualizedItem = item as IVirtualizingCanvasItem;

            if (virtualizedItem == null || 
                visibilityRect.IntersectsWith(GetBounds(virtualizedItem)))
            {
                if (generationAction == null)
                {
                    GeneratorPosition startPosition = 
                                 generator.GeneratorPositionFromIndex(index);
                    generationAction = generator.StartAt(startPosition, 
                                           GeneratorDirection.Forward, true);
                }

                GenerateItem(index);
            }
            else
            {
                GeneratorPosition itemPosition = 
                               generator.GeneratorPositionFromIndex(index);

                if (itemPosition.Index != -1 && itemPosition.Offset == 0)
                {
                    RemoveInternalChildRange(index, 1);
                    generator.Remove(itemPosition, 1);
                }

                // The generator needs to be "reseted" when we skip some items
                // in the sequence...
                if (generationAction != null)
                {
                    generationAction.Dispose();
                    generationAction = null;
                }
            }

            ++index;
        }

        if (generationAction != null)
        {
            generationAction.Dispose();
        }

        return default(Size);
    }

   (...)

    private void GenerateItem(int index)
    {
        bool newlyRealized;
        var element = 
          ItemContainerGenerator.GenerateNext(out newlyRealized) as UIElement;

        if (newlyRealized)
        {
            if (index >= InternalChildren.Count)
            {
                AddInternalChild(element);
            }
            else
            {
                InsertInternalChild(index, element);
            }

            ItemContainerGenerator.PrepareItemContainer(element);

            element.RenderTransform = _scaleTransform;
        }

        element.Measure(new Size(double.PositiveInfinity,
                                 double.PositiveInfinity));
    }

Ответы на вопрос(1)

Ваш ответ на вопрос