I recently received a mail from Marshall Price, one of the readers of my book WPF Control Development Unleashed, pointing at a bug in the sample from Chapter 8 (Virtualization). He had made some changes to the sample code in order to delete items from the StaggeredPanel. This caused a crash in the virtualized panel.
(StaggeredPanel from Chapter 8 – Virtualization)
StaggeredPanel derives from VirtualizingPanel and there is a particular
virtual method, OnItemsChanged
, that was not implemented.
OnItemsChanged
is called every time an item is
added/removed/moved/replaced in the source collection. When an item is
removed (the case for which the panel was crashing), the panel is
supposed to delete the UI container associated with the item. This
ensures that the internal data structures are in sync with the source
collection.
Providing the override for OnItemsChanged
avoids the crash. Notice the
use of RemoveInternalChildRange to remove the associated UI
container(s).
protected override void OnItemsChanged(objectsender, ItemsChangedEventArgs args)
{
base.OnItemsChanged(sender, args);
switch(args.Action)
{
case NotifyCollectionChangedAction.Remove:
case NotifyCollectionChangedAction.Move:
RemoveInternalChildRange(args.Position.Index, args.ItemUICount);
break;
}
}
If you have encountered this crash, please add this snippet to
StaggeredPanel.cs and you should be fine. Incidentally I also noticed
that loading StaggeredPanelTester.xaml
in Expression Blend causes an
exception. To circumvent that, you need to add this line at the
beginning of the method: MeasureOverride
, in StaggeredPanel.cs
:
if (availableSize.Width == double.PositiveInfinity ||
availableSize.Height == double.PositiveInfinity)
return new Size();
This line ensures that we don’t return double.PositiveInfinity as the desired size of the panel, which is the cause of the crash in Blend.
If you find any other bugs in the sample code, please feel free to email me and I’ll fix it immediately.