Xamarin Forms elements internal reuse

Nir Dil 31 Reputation points
2021-06-23T13:20:31.577+00:00

While working on a bug in a Xamarin Forms app I've find out that elements in a CollectionView are constantly reused.
Namely, if let's say I have a CollectionView with 30 elements arranged in a list, Xamarin will usually create ~10 elements and then reuse them as you scroll through the collection, by setting the BindingContext each time to the relevant model.
Only after figuring this out I managed to solve the bug as I realized I need to reset any locally changed property on BindingContext changes.
Would love any clarifications about this behavior and whether it can be tweaked as the number of created elements is very unpredictable

Developer technologies .NET Xamarin
0 comments No comments
{count} votes

Accepted answer
  1. JarvanZhang 23,971 Reputation points
    2021-06-24T05:35:53.713+00:00

    Hello,​

    Welcome to our Microsoft Q&A platform!

    Xamarin.Forms.CollectionView doesn't provide a property to set the caching mode, it automatically uses the virtualization provided by the underlying native controls. The reuse rule follows the native control, please check the correspond control of native platform to get the working mechanism. For example, CollectionView is implemented as RecyclerView on Android. RecyclerView has a view pool which reuses the item view when the items scroll out or scroll into the screen.

    Best Regards,

    Jarvan Zhang


    If the response is helpful, please click "Accept Answer" and upvote it.

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


1 additional answer

Sort by: Most helpful
  1. Nir Dil 31 Reputation points
    2021-06-25T10:17:37.047+00:00

    For UWP I ended up overriding the native control ItemsPanel and changed the default CacheLength.
    Something like this under OnElementChanged:

     if (e.NewElement is CollectionView cv &&
          Control is Windows.UI.Xaml.Controls.ItemsControl ic)
     {
          var vertical = cv.ItemsLayout is LinearItemsLayout linearLayout && linearLayout.Orientation == ItemsLayoutOrientation.Vertical;
          string xaml = "<ItemsPanelTemplate xmlns='...' xmlns:x='...'>" +
                        (Control is Windows.UI.Xaml.Controls.ListView ? "<ItemsStackPanel" : "<ItemsWrapGrid") +
                        " Orientation=" + (vertical? "'Vertical'" : "'Horizontal'") +
                        " CacheLength='10.0' />" +
                        "</ItemsPanelTemplate>";
          if (Windows.UI.Xaml.Markup.XamlReader.Load(xaml) is ItemsPanelTemplate t)
          {
               ic.ItemsPanel = t;
          }
     }
    
    1 person found this answer helpful.
    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.