Forum Xamarin.Forms

Updating ObservableCollection does not update custom ListView in Xamarin Forms

LakshyaLakshya Member ✭✭✭

I have a ListView in XAML that is bound to an ObservableCollection in the ViewModel. In initialization ListView items are displayed perfectly.

However, when I try to update the ObservableCollection at the run time, the items in the listview is does not update.

I implemented the custom listview with the help of this link -:https://stackoverflow.com/questions/49666286/xamarin-is-there-any-way-a-listview-can-be-used-horizontally

Answers

  • PrabakaranRamasamyPrabakaranRamasamy USMember ✭✭✭

    It won't work by default, it should be handled in your custom list view code. You have to invalidate the Children from the CollectionChanged event of ItemsSource property. You can refer the following code to learn how to work with collection changed event.

    https://stackoverflow.com/questions/5806172/wpf-how-do-i-hook-into-a-listviews-itemssource-collectionchanged-notification

    However, if your requirement is to make the list view horizontal, then try to use the new collection view instead of your custom list view.

    https://docs.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/collectionview/layout

  • JarvanJarvan Member, Xamarin Team Xamurai

    Updating ObservableCollection does not update custom ListView in Xamarin Forms

    1.To update listview's content, besides of using ObservableCollection, you should also make the model class to implement INotifyPropertyChanged interface to update the itemSource like below.

    public class _Model : INotifyPropertyChanged
    {
        public string content;
        public string Content
        {
            get
            {
                return content;
            }
            set
            {
                if (content != value)
                {
                    content = value;
                    NotifyPropertyChanged();
                }
            }
        }
    
        protected virtual void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    
        public event PropertyChangedEventHandler PropertyChanged;
    }
    

    2.To display ListView horizontally, try to set the Rotation property.

    <ListView x:Name="listview" Rotation="-270">
        <ListView.ItemTemplate>
            <DataTemplate>
                ...
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
    
  • LakshyaLakshya Member ✭✭✭

    @Jarvan I am binding the data in to the listview through view model , so I already implemented INotifyPropertyChanged,
    and the data in the view is upadting when using the xamain.forms listview.But doesn't updating in the case of custom listview

  • JarvanJarvan Member, Xamarin Team Xamurai

    Please post the related code or share a basic demo to reproduce the issue for a solution?

  • LakshyaLakshya Member ✭✭✭
    edited September 2019
                   <StackLayout> 
                     <control:HorizontalList  ListOrientation="Horizontal" x:Name="lst"  ItemsSource="{Binding Listsource}">
                        <control:HorizontalList.ItemTemplate>
                            <DataTemplate>
                                <ViewCell>
                                    <Frame BackgroundColor="Transparent"  WidthRequest="150" >
                                        <StackLayout>
                                            <Frame CornerRadius="10" BackgroundColor="Transparent" Padding="0">
                                                <Image Source="{Binding ImageName}" />
                                            </Frame>
                                            <Label Text="{Binding Heading}" TextColor="LightGray" FontSize="Micro" />
                                            <Label Text="{Binding Description}" TextColor="White"
                                               MaxLines="4"
                                               LineBreakMode="TailTruncation" 
                                               VerticalOptions="FillAndExpand"/>
                                        </StackLayout>
                                    </Frame>
    
                                </ViewCell>
                            </DataTemplate>
                        </control:HorizontalList.ItemTemplate>
                    </control:HorizontalList>
                 <Button Text="Add" Clicked="Add_Clicked"/>
                 </StackLayout>
    

    Xaml.cs


          public Page1()
                    {
                      InitializeComponent();
    
                       vm = new ListViewModels();
                       BindingContext = vm;
                     } 
    
           private void Add_Clicked(object sender, EventArgs e)
                {
                     vm.Add();
    
                  }
    

    ViewModel


              public class ListViewModels: INotifyPropertyChanged
                {
    
                        public  ObservableCollection<ListClass> listsource;
    
                        public ObservableCollection<ListClass> Listsource
                         {
                           get { return listsource;}
                            set
                                 {
                                            listsource= value;
                                            NotifyPropertyChanged();
                                    }
                  }
    
    
        public event PropertyChangedEventHandler PropertyChanged;
    
        protected virtual void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    
        public NewsViewModels()
        {
            FirstDataBind();
        }
    
        public void FirstDataBind()
        {
            Listsource= new ObservableCollection<ListClass>()
            {
                new ListClass{ImageName="images",Heading="Head1",Description="Test1"},
                new ListClass{ImageName="images",Heading="Head2",Description="Test1"},
                new ListClass{ImageName="images",Heading="Head3",Description="Test1"},
    
            };
    
        }
    
        public void Add()
        {
            Listsource.Add(new ListClass{ImageName="images",Heading="Head4",Description="Test1"});
        }
    
    }
    

    when i click on the add button i want to add a row into my custom listview and displays the added data

  • PrabakaranRamasamyPrabakaranRamasamy USMember ✭✭✭

    As I stated before, you have to invalidate children whenever the collection has changed from custom list view.

       private static void OnItemsSourceChanged(BindableObject bindable, object oldValue, object newValue)
        {
            (bindable as HorizontalList).OnItemsSourceChanged(oldValue, newValue);
        }
    
        private void OnItemsSourceChanged(object oldValue, object newValue)
        {
            Render();
    
            if (newValue is INotifyCollectionChanged)
            {
                (newValue as INotifyCollectionChanged).CollectionChanged += HorizontalList_CollectionChanged;
            }
    
            if (oldValue is INotifyCollectionChanged)
            {
                (oldValue as INotifyCollectionChanged).CollectionChanged -= HorizontalList_CollectionChanged;
            }
        }
    
        private void HorizontalList_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            Render();
        }
    
  • LakshyaLakshya Member ✭✭✭

    @PrabakaranRamasamy I added the code in my custom list view code.But the output is same, list view doesn't updating.

  • PrabakaranRamasamyPrabakaranRamasamy USMember ✭✭✭

    Did you call the "OnItemsSourceChanged" method from the callback of items source property?

  • JarvanJarvan Member, Xamarin Team Xamurai

    Why not use the official control CollectionView, instead of creating a custom listView? CollectionView supports horizontal orientation and data binding.

    <CollectionView ItemsSource="{Binding Monkeys}">
        <CollectionView.ItemsLayout>
            <ListItemsLayout Orientation="Vertical" />
        </CollectionView.ItemsLayout>
        ...
    </CollectionView>
    

    Check the Tutorial:
    https://docs.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/collectionview/layout

Sign In or Register to comment.