2
votes

I'm currently struggling with an issue at work, we have a ListView with the RecycleElement strategy but this is causing unexpected behaviors in the ViewCells.

When I tap on a ViewCell the first thing that happens is that the OnBindingContextChanged event is called, this happens Before the OnTapped event get's called. After pressing the ViewCell the app navigates to a different view where the user can change it's corresponding data. When the user navigates back to the previous page what should happen is that the new data that was entered should be presented in the ViewCell but this does not happen, the OnBindingContextChanged event doesn't even get fired even through I am able to get a CollectionChanged event from the ObservableCollection object which is bounded to the ListView's ItemsSource.

When I remove the CachingStrategy I get the expected behavior from the ListView ViewCells, when the user pressed the ViewCell nothing happens but when the user goes back to the original page the OnBindingContextChanged event is called and the data is properly updated.

We need the Recycle Strategy for the app's performance since it can happen that there are hundreds of items in the ListView and the app needs to stay fully responsive even when scrolling through all those items.

There isn't to much code I can share but here is what I can share

The XAML ListView definition

<ListView x:Name="TouchformList" 
    CachingStrategy="RecycleElement" 
    ItemsSource="{Binding DisplayItems}" 
    ItemTemplate="{StaticResource TouchformTemplateSelector}" 
    HasUnevenRows="True" 
    ItemSelected="Handle_ItemSelected" 
    SeparatorVisibility="None" />

DisplayItems is an ObservableCollection
BaseTouchformItem extends the ObservableObject class

Inside the ViewModel the DisplayItems are exposed like this

    private ObservableCollection<BaseTouchformItem> _displayItems = new ObservableCollection<BaseTouchformItem>(); //This object is never re-assigned elsewhere
    public ObservableCollection<BaseTouchformItem> DisplayItems
    {
        get
        {
            return _displayItems;
        }
    }

Adding items to the DisplayItems is no issue and those appear as expected.

Changing an item by simply calling DisplayItems[lastSelectedItem] = touchformItem; does raise a CollectionChanged event in the ObservableCollection as expected but when the RecycleElement strategy is active this does not propagate through to the ViewCell.

The only way I was able to get this to work was via this bad method,

DisplayItems.RemoveAt(lastSelectedItem);
await Task.Delay(50);//Horrible 'fix'
DisplayItems.Insert(lastSelectedItem, touchformItem);

But that obviously causes a UI 'glitch' by quickly removing an item and then re-adding it.

Is this potentially a bug in the ListView or is there something else going on?

1
Not sure what you are expecting, but if I' not mistaken elements in a list view would only update their data if they implement the INotifyPropertyChanged event themselves... so is this being done? And if so you'll need to load the new data in the element that is being shown in the list view - Depechie
The objects have a base class of ObservableObject which implements the INotifyPropertyChanged interface, I have found the issue and put it as an answer to this thread - MegaMiley

1 Answers

2
votes

I found the issue, for some reason the Recycle strategy doesn't like it when I swap out an object inside of the ObservableCollection, it just ignores whats happening and keeps the list as is.

The way the VM was setup was that it would re-create each item every time some data changed instead of just updating the item itself (thus making the bindings irrelevant as well), I changed it so that it updates the item itself and doesn't re-create the same item again and now it is working as expected.