0

What are the factors that virtualizingstackpanel consider when it decides visualizing items around the visible item?

Ex: Having a listview, when viewing item 7, item 6& 8 will be visualized too although they are not seen.

How can limit visualized items, so that ONLY visible item is visualized?

simo
  • 23,342
  • 38
  • 121
  • 218
  • What is visualizing? You have a ListView that only displays one items at a time? – paparazzo Oct 02 '13 at 14:37
  • 1
    If you are using .Net 4.5 you can change the property called VirtualizingStackPanel.CacheSize or something like that. Google it. – dev hedgehog Oct 02 '13 at 15:39
  • I am using .Net 4.0, @Blam, what I mean by visualizing an item is building its data template visual tree using its data model .. – simo Oct 03 '13 at 06:57
  • @"dev hedgehog" VirtualizingStackPanel.CacheSize is exactly what I need, now I have to look for a way to implement it in .Net 4.0 .. – simo Oct 03 '13 at 07:04

2 Answers2

0

Virtualization is quite a complicated subject, but I have a book that describes it well. Furthermore, this book also shows how to implement custom virtualization, which you may need to implement to achieve your goal. Luckily for you, I found that someone has posted a PDF of the book online and you can find it by clicking on this link.

The virtualization section starts on page 129, but it is well worth reading the rest of it too as it has some very interesting stuff in it.

Sheridan
  • 68,826
  • 24
  • 143
  • 183
  • Thanks, I've read that section, I found that solution in VirtualizeItems method, but, in our case we are extending VirtualizingStackPanel class, unfortunately "VirtualizeItems" method is not exposed for override .. – simo Oct 03 '13 at 07:20
  • The `VirtualizeItems` method is a custom method, it's not part of any base class. The functionality inside it could have been written straight into the `MeasureOverride` method. The only problem is that to use it, you would have to implement your own virtualization control. It *is* quite complicated, but I did it, so it is possible. Good luck if you decide to give it a try. – Sheridan Oct 03 '13 at 08:04
  • Definitely its quite complicated, will have to wisely decide. Did you see VirtualizingStackPanel.CacheSize? its in 4.5 though, migration is another problem ; – simo Oct 03 '13 at 08:24
  • I haven't seen this `CacheSize` property... according to the .NET 4.5 [VirtualizingStackPanel Class](http://msdn.microsoft.com/en-us/library/system.windows.controls.virtualizingstackpanel.aspx) page on MSDN, it does not exist. Either way, the book explains how to implement your own system pretty well and it should only take an hour or two to implement your own. – Sheridan Oct 03 '13 at 11:06
  • As the links is broken, here is an alternative one: https://github.com/adamshe/books/blob/master/WPF%20Control%20Development%20Unleashed.pdf – Bin4ry Apr 15 '22 at 22:02
0

I have solved the problem by overriding MeasureOverride function, we already purchased the book Sheridan has mentioned in his answer, depending on virtualization chapter, here is what I did to my class that extends VirtualizingStackPanel : and it worked!

private ItemsControl ItemsOwner { get; set; }
        private int StartIndex { get; set; }
        private int EndIndex { get; set; }


        protected override void OnInitialized(EventArgs e)
        {
            ItemsOwner = ItemsControl.GetItemsOwner(this) as ItemsControl;
        }


        protected override Size MeasureOverride(Size availableSize)
        {
            ItemsControl itemsControl = ItemsControl.GetItemsOwner(this);

            // we can set StartIndex& EndIndex to mimic 
            // VirtualizingStackPanel.CacheSize in .Net 4.5
            // for my problem, I just fixed them at the index of item to be shown 
            StartIndex = PagesView.Instance.SelectedIndex;
            EndIndex = StartIndex;

            // Virtualize items
            IItemContainerGenerator generator = ItemsOwner.ItemContainerGenerator;

            GeneratorPosition startPos = generator.GeneratorPositionFromIndex(StartIndex);
            int childIndex = startPos.Offset == 0 ? startPos.Index : startPos.Index + 1;
            using (generator.StartAt(startPos, GeneratorDirection.Forward, true))
            {
                for (int i = StartIndex; i <= EndIndex; i++, childIndex++)
                {
                    bool isNewlyRealized;
                    UIElement child = generator.GenerateNext(out isNewlyRealized) as UIElement;
                    if (isNewlyRealized)
                    {
                        if (childIndex >= InternalChildren.Count)
                        {
                            AddInternalChild(child);
                        }
                        else
                        {
                            InsertInternalChild(childIndex, child);
                        }
                        generator.PrepareItemContainer(child);
                    }
                }
            }



            //DumpGeneratorContent();


            // Measure
            foreach (UIElement child in InternalChildren)
            {
                child.Measure(availableSize);
            }

            // Clean up
            CleanupItems();

            return availableSize;
        }

        private void CleanupItems()
        {
            IItemContainerGenerator generator = ItemsOwner.ItemContainerGenerator;
            for (int i = InternalChildren.Count - 1; i >= 0; i--)
            {
                GeneratorPosition position = new GeneratorPosition(i, 0);
                int itemIndex = generator.IndexFromGeneratorPosition(position);
                if (itemIndex < StartIndex || itemIndex > EndIndex)
                {
                    generator.Remove(position, 1);
                    RemoveInternalChildRange(i, 1);
                }
            }
        }
simo
  • 23,342
  • 38
  • 121
  • 218