我試圖創建使用WPF列表框一個圖表控件。我創建了自己的Canvas,它來自VirtualizingPanel,我自己處理項目的實現和虛擬化。WPF列表框虛擬化創建DisconnectedItems
的ListBox的項目小組,然後設置爲我的自定義虛擬畫布。
我遇到的問題發生在以下情形:首次創建
- 列表框A項。
- 列表框項目B創建在畫布上項目A的右側。
- 列表框項目A首先被虛擬化(通過將其平移到視圖外)。
- 列表框項目B被虛擬化第二(再次通過平移它的視圖)。
- 帶上列表框項目A和B的視圖(即:實現它們)
- 使用snoop,我檢測到列表框具有現在3項,其中之一是一個「DisconnectedItem」直接位於列表框項目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));
}
您是否在回收容器? – Paparazzi
@Blam:我不認爲我是,回收容器是什麼意思? –
只是在MSDN中查找回收容器http://msdn.microsoft.com/en-us/library/system.windows.controls.virtualizationmode.aspx只是一個範圍,但也只是一個評論 – Paparazzi