Hus*_*lil 13 .net c# wpf virtualization
我正在尝试使用WPF ListBox创建Graph控件.我创建了自己的Canvas,它来自VirtualizingPanel,我自己处理项目的实现和虚拟化.
然后将列表框的项面板设置为我的自定义虚拟化画布.
我遇到的问题发生在以下场景中:
是什么导致了这个"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));
}
Run Code Online (Sandbox Code Playgroud)
我迟到了 6 年,但问题在 WPF 中仍未解决。这是解决方案(解决方法)。
对 DataContext 进行自绑定,例如:
<Image DataContext="{Binding}" />
Run Code Online (Sandbox Code Playgroud)
这对我有用,即使对于非常复杂的 xaml。
每当从可视树中删除容器时都会使用它,因为相应的项目已被删除,或者集合已刷新,或者容器已从屏幕滚动并重新虚拟化.
这是WPF 4中的已知错误
有关已知错误,请参阅此链接,它还有一个您可以应用的解决方法.
编辑:
"通过在第一次看到它时保存对sentinel对象{DisconnectedItem}的引用,然后在此之后与保存的值进行比较,您可以使解决方案更加健壮.
我们应该采用公开的方式来测试{DisconnectedItem},但它已经滑过了裂缝.我们将在未来的版本中修复它,但是现在你可以指望有一个独特的{DisconnectedItem}对象."