我想实现一个自定义Canvas
,当用作ItemsPanel
时,它会回收容器。因此,我从VirtualizingPanel
派生,并覆盖ArrangeOverride
和MeasureOverride
。我正在MeasureOverride
中进行这样的生成:
var children = base.InternalChildren;
var itemsControl = ItemsControl.GetItemsOwner(this);
var itemsCount = itemsControl.Items.Count;
IItemContainerGenerator generator = itemsControl.ItemContainerGenerator;
var startPos = generator.GeneratorPositionFromIndex(0);
using (generator.StartAt(startPos, GeneratorDirection.Forward, true))
{
for (int i = 0; i < itemsCount; i++)
{
bool isNewlyRealized;
var child = generator.GenerateNext(out isNewlyRealized) as UIElement;
if (isNewlyRealized)
{
base.AddInternalChild(child);
generator.PrepareItemContainer(child);
}
child.Measure(constraint);
}
}
我不知道如何进行回收。我试过以下的东西:
protected override void OnItemsChanged(object sender, ItemsChangedEventArgs e)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Remove:
case NotifyCollectionChangedAction.Replace:
case NotifyCollectionChangedAction.Move:
IRecyclingItemContainerGenerator generator = ItemsControl.GetItemsOwner(this).ItemContainerGenerator;
generator.Recycle(e.Position, e.ItemUICount);
RemoveInternalChildRange(e.Position.Index, e.ItemUICount);
break;
}
}
但它不起作用。知道怎么做吗?
答案 0 :(得分:3)
看这里: http://blogs.claritycon.com/blogs/lee_roth/default.aspx
我按以下方式进行回收:
在OnItemsChanged
中,我只拨打RemoveInternalChildRange
:
protected override void OnItemsChanged(object sender, ItemsChangedEventArgs args)
{
switch (args.Action)
{
case NotifyCollectionChangedAction.Remove:
case NotifyCollectionChangedAction.Replace:
RemoveInternalChildRange(args.Position.Index, args.ItemUICount);
break;
case NotifyCollectionChangedAction.Move:
RemoveInternalChildRange(args.OldPosition.Index, args.ItemUICount);
break;
}
}
在Measure覆盖中,我首先添加新项目,然后删除旧项目。 如果您使用回收,您必须知道如果您获得回收容器,通过调用GenerateNext获得的新标志也是假的。
这里我们添加新项目:
GeneratorPosition start = ItemContainerGenerator.GeneratorPositionFromIndex(iFirstItemIndex);
int iChildIndex = (start.Offset == 0) ? start.Index : start.Index + 1;
using (ItemContainerGenerator.StartAt(start, GeneratorDirection.Forward, true))
{
for (int i = iFirstItemIndex; i <= iLastItemIndex; i++, iChildIndex++)
{
bool bNew;
UIElement element = (UIElement)ItemContainerGenerator.GenerateNext(out bNew);
//If we get a new instance
if (bNew)
{
if (iChildIndex >= Children.Count) AddInternalChild(element);
else InsertInternalChild(iChildIndex, element);
ItemContainerGenerator.PrepareItemContainer(element);
}
//If we get a recycled element
else if (!InternalChildren.Contains(element))
{
InsertInternalChild(iChildIndex, element);
ItemContainerGenerator.PrepareItemContainer(element);
}
element.Measure(...);
}
}
添加项目后,我们删除旧项目:
for (int i = Children.Count - 1; i >= 0; i--)
{
GeneratorPosition childGeneratorPosition = new GeneratorPosition(i, 0);
int iIndex = ItemContainerGenerator.IndexFromGeneratorPosition(childGeneratorPosition);
if (iIndex < iFirstItemIndex || iIndex > iLastItemIndex)
{
//remove() calls ItemContainerGenerator.remove() OR recycle(). Both works.
remove(childGeneratorPosition, 1);
RemoveInternalChildRange(i, 1);
}
}
我希望我能帮到你。