Is this a bug in binding to ItemsSource of ListView?

xmaaxmaa CZMember

Hi,
I have prepared minimal project to reproduce the issue.

The problem is when removing item from ObservableCollection<> binded to ItemsSource of ListView then the BindingContext of ViewCell is set for a while to the object being removed.

Run the project in Android emulator and when you click 'Remove' button then you can see in debug output this message about strange binding error:
[0:] Binding: 'Part' property not found on 'XamBugListView01.MainPage+ItemPart', target property: 'Xamarin.Forms.Label.BindingContext'

The project uses Xamarin.Forms 2.3.3.193.

Here is the source code of MainPage.xml.cs:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;

namespace XamBugListView01
{
    public partial class MainPage : ContentPage
    {
        private ObservableCollection<Item> _allItems = new ObservableCollection<Item>();

        public MainPage()
        {
            _allItems.Add(new Item());
            _allItems.Add(new Item());

            InitializeComponent();

            _listView.BindingContext =
                new
                {
                    AllItems = _allItems
                };
        }

        private void RemoveClicked(object sender, EventArgs ea)
        {
            _allItems.RemoveAt(0);
        }

        public class Item
        {
            public ItemPart Part { get; private set; }

            public Item()
            {
                Part = new ItemPart();
            }
        }

        public class ItemPart
        {
            private static int _counter;

            public string Name { get; private set; }

            public ItemPart()
            {
                Name = "item part " + (++_counter);
            }

            //public ItemPart Part
            //{
            //    get
            //    {
            //        throw new InvalidOperationException("Property Part of ItemPart is never used in any code and any XAML.");
            //    }
            //}
        }
    }
}

Here is the source code of MainPage.xml:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:XamBugListView01"
             x:Class="XamBugListView01.MainPage">

  <StackLayout Orientation="Vertical">

    <ListView Grid.Row="1"
              x:Name="_listView"
              ItemsSource="{Binding Path=AllItems}"
              HorizontalOptions="FillAndExpand"
              VerticalOptions="FillAndExpand">
      <ListView.ItemTemplate>
        <DataTemplate>
          <ViewCell>
            <Label BindingContext="{Binding Path=Part}" Text="{Binding Path=Name}" />
          </ViewCell>
        </DataTemplate>
      </ListView.ItemTemplate>
    </ListView>

    <Button Text="Remove"
            Clicked="RemoveClicked" />

  </StackLayout>

</ContentPage>

Everything else is generated from the template 'Blank Xaml App (Xamarin.Forms.Portable) C#' (project name is XamBugListView01).

Whole solution is attached in ZIP archive.

Best Answer

Answers

  • AlessandroCaliaroAlessandroCaliaro ITMember ✭✭✭✭✭

    two errors

        private void RemoveClicked(object sender, EventArgs ea)
        {
        if(_allItems.Count( ) > 0)
                    _allItems.RemoveAt(0);
        }
    

    and

      <ListView.ItemTemplate>
        <DataTemplate>
          <ViewCell>
            <Label  Text="{Binding Part.Name}" />
          </ViewCell>
        </DataTemplate>
      </ListView.ItemTemplate>
    
  • xmaaxmaa CZMember

    @AlessandroCaliaro

    Ok, the first is error but it is not important to this problem. The binding to the BindingContext is on purpose because I use it in more complex code and this is only the MINIMAL code to reproduce the problem. Or it is forbidden to bind to the BindingContext?

    Thanks for your time and your comment.

  • AlessandroCaliaroAlessandroCaliaro ITMember ✭✭✭✭✭

    In ViewCell the BindingContext is already bind when you write (in listview)

              ItemsSource="{Binding Path=AllItems}"
    
  • xmaaxmaa CZMember

    I know. But image more complex situation. This is example: you want to display all animals in ZOO in ListView. Then you have these ViewModels for animal types (I will omit some details which are not important here like access rights and members of some classes):

    abstract class AnimalTypeViewModel { ... }
    class AnimalTypeTigerViewModel : AnimalTypeViewModel { ... }
    class AnimalTypeMonkeyViewModel : AnimalTypeViewModel { ... }
    

    And this ViewModel for real animals:

    class AnimalViewModel {
      public string AnimalName { get; set; } // e.g. Mickey, Dundee, Goofy
      public AnimalTypeViewModel AnimalType { get; set; }
    }
    

    Then the MainPageViewModel looks like this:

    class MainPageViewModel {
      public ObservableCollection<AnimalViewModel> AllAnimals { get; set; }
    }
    

    There is custom user interface control to display different animal types in the project:

    class AnimalTypeView : ContentView { ... }
    

    Then the ListView in the MainPageView.xaml is here:

    <ListView Grid.Row="1"
              x:Name="_listView"
              ItemsSource="{Binding Path=AllAnimals}"
              HorizontalOptions="FillAndExpand"
              VerticalOptions="FillAndExpand">
      <ListView.ItemTemplate>
        <DataTemplate>
          <ViewCell>
            <StackLayout Orientation="Horizontal">
              <Label Text="{Binding Path=AnimalName}" />
              <local:AnimalTypeView BindingContext="{Binding Path=AnimalType}" />
            </StackLayout>
          </ViewCell>
        </DataTemplate>
      </ListView.ItemTemplate>
    </ListView>
    

    In this example you can not avoid binding to BindingContext because it is nonsense to expect that the BindingContext's type of AnimalTypeView is AnimalViewModel type. Its type must be AnimalTypeViewModel. Do you agree?

  • xmaaxmaa CZMember

    @JimmyGarrido said:
    Hmm, this might be an issue in Forms. Can you file a bug report and attach your repro project so we can look into it? If this is a bug then we can use the report to track it. Thanks!

    Ok and thanks, I have submitted the report here:
    https://bugzilla.xamarin.com/show_bug.cgi?id=53987

Sign In or Register to comment.