.net WPF物品容器回收
我想实现一个自定义的.net WPF物品容器回收,.net,wpf,itemscontrol,recycle,itemcontainergenerator,.net,Wpf,Itemscontrol,Recycle,Itemcontainergenerator,我想实现一个自定义的画布,当用作项目span时,它会回收容器。因此,我从virtualzingpanel派生并覆盖ArrangeOverride和MeasureOverride。我在MeasureOverride中进行生成,如下所示: var children = base.InternalChildren; var itemsControl = ItemsControl.GetItemsOwner(this); var itemsCount = itemsControl.Items.Coun
画布
,当用作项目span
时,它会回收容器。因此,我从virtualzingpanel
派生并覆盖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);
}
}
但它不起作用。你知道怎么做吗?看看这里:
我通过以下方式进行回收:
在OnItemChanged
中,我只调用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;
}
}
在“度量值覆盖”中,我首先添加新项,然后删除旧项。
如果您使用回收,您必须知道,如果您使用的是回收容器,则通过调用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(...);
}
}
GeneratorPosition start=ItemContainerGenerator.GeneratorPositionFromIndex(iFirstItemIndex);
int iChildIndex=(start.Offset==0)?start.Index:start.Index+1;
使用(ItemContainerGenerator.StartAt(start,GeneratorDirection.Forward,true))
{
对于(int i=iFirstItemIndex;i=Children.Count)AddInternalChild(元素);
else InsertInternalChild(iChildIndex,元素);
ItemContainerGenerator.PrepareItemContainer(元素);
}
//如果我们得到一个可回收的元素
如果(!InternalChildren.Contains(元素))为else
{
InsertInternalChild(iChildIndex,元素);
ItemContainerGenerator.PrepareItemContainer(元素);
}
元素。度量(…);
}
}
添加项目后,我们将删除旧项目:
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);
}
}
for(int i=Children.Count-1;i>=0;i--)
{
GeneratorPosition childGeneratorPosition=新的GeneratorPosition(i,0);
int iIndex=ItemContainerGenerator.IndexFromGeneratorPosition(childGeneratorPosition);
如果(iIndexiLastItemIndex)
{
//remove()调用ItemContainerGenerator.remove()或recycle()。两者都可以工作。
移除(儿童发电机位置,1);
RemoveInternalChildRange(i,1);
}
}
我希望我能帮助您。事实上,如果您正在回收,您应该在生成新容器之前调用“清理”代码(最后一个代码块)。这是因为您希望在需要可用容器之前而不是之后回收它们。保存一些不需要的创建。链接不再可用。
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);
}
}