Listview item GUI does not update properly when property changed (on Android only)

gvuksagvuksa RSMember ✭✭

I am having the strangest issue using Xamarin.Forms. I have a simple listview with items source binded to ObservableRangeCollection property on page model.

In listview item, a label should only be visible when item is tapped. I achieve this by binding this label IsVisible property to IsSelected bool property in item source object.

Anyway, when listview is loaded, and I tap on one of the items, everything works as expected. I can tap on several items, and each one will be properly updated. But when I scroll down to the items that were not on screen and tap on one of those, nothing happens. Then when I scroll again (up or down), so that the tapped item is no longer on screen, and then scroll back so that the tapped item returns on screen, item is updated.

This is only happening on android, on iOS it works fine.

Does anyone have any idea what could be causing this?

Answers

  • clopezclopez ESMember ✭✭✭

    I'm not an expert but it looks like that's something to do with the ListView behaviour. You know that the list view can handle its items recycling the view or creating one per element. Just look at "catching strategic" here:
    https://docs.microsoft.com/es-es/xamarin/xamarin-forms/user-interface/listview/performance

    Maybe is a problem with it, and changing the catching strategic will work. Or maybe is your initialization method of the cell.
    Or maybe you can solve it just updating Xamarin: I had to solve some text alignment issues.

  • JarvanJarvan Member, Xamarin Team Xamurai

    Could you post the related code to reproduce the issue?

  • gvuksagvuksa RSMember ✭✭

    @clopez I had tried all caching strategies, and have the latest version of Xamarin.Forms

    @yelinzh Just create a simple Listview bind it to ObservableCollection or ObservableRangeCollection of a model that inherits INotifyPropertyChanged and has IsSelected bool property. And on Listview items templated add data template with view cell that has a label in a grid, and visibility of that label is binded to IsSelected property.

  • JarvanJarvan Member, Xamarin Team Xamurai

    Change the 'IsSelected' property in ItemTapped event. You can refer to the code:
    page.xaml

    <ListView x:Name="listview" ItemTapped="Listview_ItemTapped">
        <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell>
                    <StackLayout>
                        <Label Text="{Binding Content}" IsVisible="{Binding IsSelected}"/>
                    </StackLayout>
                </ViewCell>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
    

    page.xaml.cs

    public partial class Page2 : ContentPage
    {
        ObservableCollection<_Model> list = new ObservableCollection<_Model>();
        public Page2()
        {
            InitializeComponent();
    
            list.Add(new _Model { content = "label_1", isSelected = true });
            list.Add(new _Model { content = "label_2", isSelected = false });
            list.Add(new _Model { content = "label_3", isSelected = true });
            //   list.Add(new _Model { name = "aaaa" });
            listview.ItemsSource = list;
        }
    
        private void Listview_ItemTapped(object sender, ItemTappedEventArgs e)
        {
            _Model model = (_Model)e.Item;
            model.IsSelected = true;
        }
    }
    
    public class _Model : INotifyPropertyChanged
    {
        public bool isSelected;
        public bool IsSelected
        {
            get
            {
                return isSelected;
            }
            set
            {
                if (isSelected != value)
                {
                    isSelected = value;
                    NotifyPropertyChanged();
                }
            }
        }
        ...
    
        protected virtual void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    
        public event PropertyChangedEventHandler PropertyChanged;
    }
    

Sign In or Register to comment.