【发布时间】:2012-12-26 07:32:47
【问题描述】:
我正在尝试使用 WPF 列表框创建图形控件。我创建了自己的 Canvas,它派生自 VirtualizingPanel,我自己处理项目的实现和虚拟化。
然后将列表框的项目面板设置为我的自定义虚拟化画布。
我遇到的问题发生在以下场景:
- 首先创建列表框项 A。
- ListBox 项目 B 创建在画布上项目 A 的右侧。
- 首先虚拟化列表框项 A(通过将其移出视图)。
- ListBox 项目 B 是第二个虚拟化的(再次通过将其移出视图)。
- 在视图中显示 ListBox 项 A 和 B(即:实现它们)
- 使用 Snoop,我检测到 ListBox 现在有 3 个项目,其中一个是位于 ListBox 项目 B 正下方的“DisconnectedItem”。
是什么导致了这个“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));
}
【问题讨论】:
-
你在回收容器吗?
-
@Blam:我想我不是,你说回收容器是什么意思?
-
只需在 msdn 中搜索回收容器 msdn.microsoft.com/en-us/library/… 只是一个范围,也只是一个评论
-
@Blam:谢谢,我尝试使用 VirtualizingStackPanel 并打开容器回收。不幸的是我仍然有同样的问题,即:当项目被虚拟化时,正在生成 DisconnectedItems。
标签: c# .net wpf virtualization