Search code examples
visual-studiolistviewxamarin.androidandroid-arrayadapter

Updating the list view when the adapter data changes, in visual-studio android sdk


My Listview with Adapter and collection of items in visual studio xamarine android sdk (native UI) does not get updated when items changes. I' m using the following code to have a list of items in visual-studio-xamarine. it seems to work, except that the list is not updated when an item is altered, added or deleted to the collection.

Should I follow a different approach? What needs to be done so that the listview listens for items changes?

My custom adapter

public class TableItemAdapter : BaseAdapter<Table>
{
    List<Table> items;
    Activity context;

    public TableItemAdapter(Activity context, IEnumerable<Table> items) : base() {
        this.context = context;
        this.items = items.ToList();
    }

    public override View GetView(int position, View convertView, ViewGroup parent)
    {
        View view = convertView;        // re-use an existing view, if one is available
        if (view == null)               // otherwise create a new one
            view = context.LayoutInflater.Inflate(Resource.Layout.TableListItem, null);

        var tableName = view.FindViewById<TextView>(Resource.Id.tvTableName);
        tableName.Text = items[position].TABLE_NAME;
        tableName.SetTextColor(items[position].tableColor);

        view.FindViewById<TextView>(Resource.Id.tvTableDetail).Text = items[position].Rest;
        return view;
    }

    public override long GetItemId(int position) { return position; }
    public override Table this[int position] { get { return items[position]; } }
    public override int Count { get { return items.Count; } }
}

TableListItem.xml

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/RelativeLayout01" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent"
    android:padding="10dp" >

<TextView 
    android:id="@+id/tvTableName"
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content"
    android:layout_alignParentLeft="true"
    android:textSize="20sp" />

<TextView 
    android:id="@+id/tvTableDetail"
    android:layout_width="match_parent" 
    android:layout_height="wrap_content"
    android:layout_toRightOf="@+id/tvTableName"
    android:gravity="right"/>

</RelativeLayout>

c#

private ObservableCollection<Table> tables = new ObservableCollection<Table>();
fillTablesWithObjects(tables); // adding items to collection

listView = FindViewById<ListView>(Resource.Id.lvTables);
var lvAdapter = new TableItemAdapter(this, tables);
listView.Adapter = lvAdapter;

// when adding or altering tables, nothing happens to listview
tables.Add(new Table() { Name = "Table A1" });

NotifyDataSetChanged, listView.listSource, etc do not seem to be xamarine android sdk, which is what I need.


Solution

  • The problem is that tables instance (in c# section) is the one that gets updated but TableItemAdapter keeps a separate List internally and that's the one that should get updated instead.

    Then NotifyDataSetChanged() will work! So...

    My custom adapter

    public class TableItemAdapter : BaseAdapter<Table>
    {
        List<Table> items;
        ...
        public void Update(IEnumerable<Table> tables)
        {
            items.Clear();
            items.AddRange(aItems);
            NotifyDataSetChanged();
        }
    }
    

    c#

    ...
    tables.Add(new Table() { Name = "Table A1" });
    lvAdapter.Update(tables); // <-- call this everytime tables change
    

    The code can be optimized, so that only one list of objects is used, by adding a method in the custom adapter to return its List<Table> items and using that instead of creating another List for tables.