ListView binding to ObservableCollection does not update GUI

mkvonarxmkvonarx USMember

Hi

Can anyone tell me why this simple code is not working as expected? Does the ListView control not listen for changes in the bound property?

  • Expected: when I click the Add button, the GUI (ListView) updates through the binding and shows the new element in the ObservableCollection.
  • Observed: GUI does not update but always shows the initial three items of the ObservableCollection.
  • Btw: OnAddButtonClicked() does get called and ListViewItems does get updated (checked in the debugger). Calling OnPropertyChanged("ListViewItems") inside OnAddButtonClicked() did not help either.
  • And: if I update the code as follows, the ListView works: add a Label control, bind that label to a 2nd property, update that property inside OnAddButtonClicked(), call OnPropertyChanged() from inside the property setter. So obviously this call to OnPropertyChanged() somehow triggers the ListView to get updated as well...
  • I'm now using Xamarin.Forms version 1.1.0.6201. Didn't work with the previous version either.

XAML:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="Test1.MainPage"
             Padding="10" Title="MainPageXaml">
    <StackLayout VerticalOptions="StartAndExpand" HorizontalOptions="Fill">
        <Button Text="Add" Clicked="OnAddButtonClicked" />
        <ListView ItemsSource="{Binding ListViewItems}" />
    </StackLayout>
</ContentPage>

C#:

public partial class MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();
        ListViewItems = new ObservableCollection<string> { "one", "two", "three" };
        BindingContext = this;
    }

    private void OnAddButtonClicked(object sender, EventArgs e)
    {
        ListViewItems.Add(DateTime.Now.ToString());
        // OnPropertyChanged("ListViewItems");
    }

    public ObservableCollection<string> ListViewItems { get; set; }
}

Markus

«13

Posts

  • EricMaupinEricMaupin USXamarin Team Xamurai

    This should work. Which platform(s) have you tried on?

  • mkvonarxmkvonarx USMember
    edited June 2014

    This:

    • Visual Studio 2013 Update 2
    • Xamarin 3.0.54.0, Xamarin.Android 4.12.4.20 (as shown in VS), evaluation licence
    • Xamarin.Forms 1.1.0.6201
    • Xamarin.Android.Support.v4 19.0.2
    • "standard" new project -> Mobile Apps -> Xamarin.Forms Portable
      ** only change done by me: disabled fast deployment (didn't work with Samsung Note 2)
    • Windows 8.1 Update 1 64bit
    • JDK 1.6.0_45

      • btw: why not JDK 8, or at least JDK 7? 1.6 is not even easily downloadable anymore and full of bugs
    • all the Android SDK's that Xamarin downloaded ("many": 4.0.3, 3.1, 2.2.3, 2.2, 2.1) over the one I've already had installed from Android SDK (SDK Tools 22.6.4; SDK Platform 4.4.2 ~ API 19, rev 3)

      • -> btw: couldn't you reduce the number of required Android SDK's? I mean: version 2 & 3 ....
    • tests on Samsung Note 2 (GT-N7105), Android 4.3, more or less using factory defaults, no SIM card, has WLAN

  • mkvonarxmkvonarx USMember

    Another update: I found the following errors message in the Android Device Logging (open via View -> Other -> Android Device Logging):

    DatabaseUtils: Writing exception to parcel
    DatabaseUtils: java.lang.SecurityException: Permission Denial: get/set setting for user asks to run as user -2 but is calling from user 0; this requires android.permission.INTERACT_ACROSS_USERS_FULL
    ... (stack trace)
    ActivityManager: Permission Denial: Permission Denial: get/set setting for user asks to run as user -2 but is calling from user 0; this requires android.permission.INTERACT_ACROSS_USERS_FULL
    

    (btw: why can't I copy-paste from the Android Device Logging window? this is really annoying)

    My first thought was that this might be caused by the "Use Shared Runtime" option. So I tried without a shared runtime. Same resultes. I also tried adding the INTERACT_ACROSS_USERS_FULL permission, but that didn't work either (and I think it's not possible to request that permission by an app anyway).

  • HugoLogmans_HugoLogmans_ NLMember ✭✭✭

    @mkvonarx, did you check if you can scroll to the added item? There is an issue where the listview bounds are not updated, although the item IS added (but just not visible). I have this type of code working fine...

  • mkvonarxmkvonarx USMember

    @HugoLogmans, I just checked and you're right: the items are added to the ListView, but the ListView bounds are unchanged and the new items are therefore not visible. So issue solved, or at least relegated to a layouting problem. Thanks!

  • M2MM2M USMember ✭✭

    Hi @mkvonarx‌ ,
    How did you resolve this problem?
    I get the same problem. After reloading the observationcollection datasource, nothing change but if I rotate the device the listview update and show the items correctly

  • mkvonarxmkvonarx USMember

    Hi @maidinhnga‌
    Well... My first workaround was to manually set the size of the ListView control. But finally I completely gave up on Xamarin.Forms and went back to using native Android AXML for the Android GUIs because Xamarin.Forms is just not mature (feature rich, bug free) enough for my needs, e.g. I couldn't even set the font size on some controls.
    Markus

  • Faisal.2778Faisal.2778 USMember ✭✭

    Any idea how this would work? Is there a way to force the list to reload data/render again. For me this problem repro on WP not on iOS

  • GaborFurediGaborFuredi HUMember ✭✭

    Just ran into this bug as well. Any news on a possible fix?

  • MateVargaMateVarga DEMember
    edited September 2014

    Yep, it's extremely annoying -- ListViews + ObservableCollections are used everywhere. It'd be great to have an ETA for the fix... (i can repro it on iOS).

  • The work around is to encapsulate the list inside a grid with a row height of '*'

  • PaulFitzpatrickPaulFitzpatrick GBMember ✭✭
    edited September 2014

    Is there a fix for this anytime soon? I am evaluating the product and have been fairly impressed so far although this is a real nightmare for a Xamarin novice. Can someone post the code for work around. I am running the latest codebase.

    Thanks in advance.

  • KyleKyle USMember

    @RobCrabtree‌
    Could you elaborate?

  • @Kyle‌, This solves the problem, notice the _RowDefinition _with a height of '*'. This instructs the row to consume the remaining space, this list then fills the row. Without this the height of the list has to be manually controlled. Let us know if this solves your problem.

    <Grid>
        <Grid.RowDefinitions>
          <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <ListView  ItemsSource="{Binding Path=MyItems}" HasUnevenRows="True"  >
          <ListView.ItemTemplate>
            <DataTemplate>
              <ViewCell>
                <ViewCell.View>
                  <StackLayout>
                    <Label Text="{Binding Line1}"  />
                    <Label Text="{Binding Line2}"  />
                  </StackLayout>
                </ViewCell.View>
              </ViewCell>
            </DataTemplate>
          </ListView.ItemTemplate>
        </ListView>
      </Grid>
    
  • @Kyle‌ Your solution works :)

  • @Kyle thanks mate, you got me partially there. GridUnitType.Star didn't work, but just using Grid in general seems to work.

    I couldn't use GridUnitType.Star just like you described because the other StackLayouts didn't adjust accordingly and I ended up with what I presume to be controls overlapping, effectively not showing the buttons I needed to show to add rows into my ListView.

    After re-factoring, just using Grid as a container with a fixed height, I could test and confirm.
    For the test my container grid is defined as:

    Grid grid = new Grid();
    grid.RowDefinitions.Add(new RowDefinition() { Height = page.Height - 200 });            
    grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star) });
    

    I had to subtract 200 from the page height because for the moment I can't get my layouts to play together in the sand pit, they keep fighting.

  • I have a similar scenario. ListView doesn't update (even when wrapped in a grid). However, tapping a toggle switch in the same view miraculously updates the UI. Seems like some kind of render refresh issue.

  • infidelinfidel FIMember

    Had a similar issue with a TabbedPage containing ContentPages with ListViews. Lists were empty unless I rotated to landscape to enforce a layout update. A workaround was to add UpdateChildrenLayout(); in PageChanged event handler.

    It's worth noting that I have this issue only when wrapping the TabbedPage inside NavigationPage.

  • BRHBRH USMember ✭✭

    @ermau‌ It seems a lot of people have this bug; do you know if it was ever fixed? I'm running into the same problem.

  • AlanTonissonAlanTonisson AUMember ✭✭
    edited January 2015

    I also have the same problem. Anyone know when it will be fixed?
    I'm using code to build my UI instead of XAML.
    I explicitly reset the ItemsSource, but it makes no difference.
    Other views update correctly, but the ListView does not.

  • Same as you guys... TabbedPage + ListView + ObservableCollection = nightmare ... i'm sending a message to updatelayout eachtime i load the datasource. It's better but still have some empty list while everything isn't empty ...

  • DanielLDanielL PLInsider ✭✭✭✭
    edited January 2015

    TabbedPage + ListView has also problem with ListView.ScrollTo method (it doesn't work every time on Android)

  • ThomasHagstrmThomasHagstrm SEMember ✭✭
    edited January 2015

    I've developed XAML+C# for Silverlight for years. Took me a while to get this working though.
    My solution was an old trick to clear the ListView.ItemsSource completely whenever CollectionChanged occured on the source collection. UpdateLayout didn't help.

    In my ContentView I have a control named ListViewItems as well as the BindableProperty this.ItemsSource (write those with a nice ReSharper template!) to initially supply the source collection.

    When I get the collection I start listening to CollectionChanged:

            private static void ItemsSourceChanged(BindableObject bindable, IEnumerable oldValue, IEnumerable newValue)
            {
                var hliListBox = ((HliListBox)bindable);
                hliListBox.ListViewItems.ItemsSource = newValue;
                var obs = newValue as INotifyCollectionChanged;
                if (obs != null)
                {
                    obs.CollectionChanged -= hliListBox.Update;
                    obs.CollectionChanged += hliListBox.Update;
                }
            }
    

    The Update method then flushes the ListView's source and re-sets it.

            private void Update(object sender, NotifyCollectionChangedEventArgs e)
            {
                this.Update();
            }
    
            private void Update()
            {
                var src = this.ItemsSource;
                this.ItemsSource = null;
                this.ListViewItems.ItemsSource = null;
                this.ItemsSource = src;
                this.ListViewItems.ItemsSource = this.ItemsSource;
            }
    

    I might be crazy but can't get the thing to work otherwise. This is a Xamarin Forms 1.3 PCL project.

  • rizkyariorizkyario USMember ✭✭

    Just encountered this problem,
    It happens when creating(declaring through XAML in my case) a Custom ContentView that contains the ListView Object more than once. Xamarin only updates the last created ListView Object.

    Solved it by creating new ContentView instead of reusing the existing one.

  • I've reproduced the problem in simple form here

  • AlessandroCaliaroAlessandroCaliaro ITMember ✭✭✭✭✭

    There is a solution to this problem?

  • prashantvcprashantvc USXamarin Team Xamurai

    It's sounds like a bug in Xamarin.Forms, I have already filed it on Bugzilla here: https://bugzilla.xamarin.com/show_bug.cgi?id=26418, it will be easy for you guys to track it.

    If you add yourself to the CC list in that bug report, you'll automatically be emailed whenever the report is updated; including any workarounds that our engineers find in the process of working on the bug.

  • JohnMichaelHauckJohnMichaelHauck USMember
    edited January 2015

    I suspect this may be the same issue as Bug 23585, Reported: 2014-10-03

  • AlanTonissonAlanTonisson AUMember ✭✭
    edited January 2015

    I think there are actually two issues. I solved the updating problem by explicitly resetting ItemSource like @ThomasHagstrm does, but there was another issue also: I noticed that the list remains empty when I start adding items one at a time. This is on Android BTW, I haven't tested iOS.

    I then found that the items appear when I touch the list. The problem seems to be that the items are scrolled out of view. Of course ScrollTo does not actually seem to work. :-(

  • ThomasHagstrmThomasHagstrm SEMember ✭✭

    Have anyone reported this in Xamarin's bugzilla?

  • AlessandroCaliaroAlessandroCaliaro ITMember ✭✭✭✭✭

    Is it been resolved?

  • VictorArceVictorArce USMember

    Try Adding...
    ViewModel.Dashboards.CollectionChanged += Dashboards_CollectionChanged;

    It will only trigger only if the collection changes, not individual properties.
    To workaround this, try clearing the collection then adding items one-by-one.

    If I just set the collection after clearing it doesn't trigger.

    It works but its not optimal. Anyone has another idea?

  • TonyDTonyD USMember ✭✭✭

    Hi - any updates on this bug?

  • pwojtowiczpwojtowicz USMember ✭✭

    Same here, hours lost due to this... any fix planned after 6 months when bug is known and provided to Xamarin devs?

  • LatziLatzi USMember

    Hi,

    in the bug https://bugzilla.xamarin.com/show_bug.cgi?id=26418 Jason Smith wrote on 2015-05-21 it shall be fixed in the next release. But what version is this and when did we get this?

    greetings

  • ShantimohanElchuriShantimohanElchuri USMember ✭✭✭✭✭

    @Latzi The Xamarin.Forms version 1.4.4 was released on July 27, 2015 and this is the latest. Did you check if it is resolved.

    Also, has anyone tried placing the ListView in a ScrollView?

    I had similar issue as changes to an ObservableCollection doesn't update the ListView. I had no issue with adding an item but when an item is modified or deleted the ListView doesn't refresh.

    Item Update:

    1. I delete the item and insert it at the same point.
    2. In WP no issue.
    3. In Android, I have to do it in the "Save" action method.
    4. In iOS, I have to do it in the OnAppearing() override in the page where the ListView is residing.

    Item Delete: I am still working on it. The item is deleted from the collection but the ListView is not reflecting it. The app has to be restarted to see that the item is deleted. But one more issue with iOS is that when you exit the app by pressing the Home button, the app is actually in the suspended state and a snapshot of the current page is saved. So when you restart the app, the last snapshot stored is displayed. You will have to actually kill the app by swiping in the suspended app list and restart the app.

  • I tried 1.4.4 and it's still a problem. Only tried on Android. My work around is to add and remove a temporary item, this way I don't mess with the real data.

  • MartinStievenartMartinStievenart USMember, University ✭✭

    As mentionned by @RobCrabtree fixing the height of the Grid to * works.
    But the ListView should have the HasUnevenRows="true", if the RowHeight is set it's not working.

Sign In or Register to comment.