添加到绑定ObservableCollection(Xamarin)的元素后ListView不更新

时间:2016-11-24 06:23:14

标签: android listview xamarin observablecollection

我在StackOverflow上发现了许多类似的问题,但似乎无法弄清楚这个问题。

我试图将ObservableCollection绑定到ListView,以便当集合的内容发生更改时,ListView将自动更新。不幸的是,当元素添加到集合中时(通过按钮单击),ListView不会被更新。如何使ListView反映集合的当前内容?

注意:如果我使用listView.RequestLayout();强制布局,listView将包含正确数量的项目。但是,它不一定包含项。例如,如果我删除第一个项目并在末尾添加新项目,则强制布局无效。如果我在删除第一个项目后强制执行布局,则在最后添加一个项目后再次强制执行布局,内容是正确的。

活动代码

public class MainActivity : Activity
{
    int count = 1;

    protected override void OnCreate(Bundle bundle)
    {
        base.OnCreate(bundle);

        ObservableCollection<UserTask> allTasksCollection = new ObservableCollection<UserTask>();
        while(count < 6)
        {
            allTasksCollection.Add(new UserTask("Task number " + count));
            count++;
        }

        // Set our view from the "main" layout resource
        SetContentView(Resource.Layout.Main);

        // Bind listview to all tasks
        ListView listView = FindViewById<ListView>(Resource.Id.allTasksListView);
        UserTaskListAdapter adapter = new UserTaskListAdapter(this, allTasksCollection);
        listView.Adapter = adapter;

        // Button click should add a new task and remove the first task. 
        Button button = FindViewById<Button>(Resource.Id.myButton);
        button.Click += delegate {                
            allTasksCollection.Add(new UserTask("Task number " + count));
            button.Text = string.Format("{0} tasks!", count++);
        };
    }
}

适配器

public class UserTaskListAdapter : BaseAdapter<UserTask>
{
    Activity context;
    ObservableCollection<UserTask> list;

    public UserTaskListAdapter(Activity _context, ObservableCollection<UserTask> _list)
    : base()
    {
        this.context = _context;
        this.list = _list;
    }

    public override int Count
    {
        get { return list.Count; }
    }

    public override long GetItemId(int position)
    {
        return position;
    }

    public override UserTask this[int index]
    {
        get { return list[index]; }
    }

    public override View GetView(int position, View convertView, ViewGroup parent)
    {
        View view = convertView;
        if (view == null)
            view = context.LayoutInflater.Inflate(Resource.Layout.UserTaskRowItem, parent, false);

        UserTask item = this[position];
        view.FindViewById<TextView>(Resource.Id.Title).Text = item.Name;

        return view;
    }
}

主要XAML

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:id="@+id/rootLayout">
        <LinearLayout
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/allTasksContainer">
            <Button
                android:id="@+id/myButton"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="@string/hello" />
            <ListView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:id="@+id/allTasksListView" />
        </LinearLayout>
</LinearLayout>

ListItem XAML

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content">
    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/linearLayoutHorizontal">
        <LinearLayout
            android:orientation="vertical"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/CheckboxContainer">
            <CheckBox
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:id="@+id/checkboxSelect" />
        </LinearLayout>
        <LinearLayout
            android:orientation="vertical"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/TextContainer">
            <TextView
                android:text="Large Text"
                android:textAppearance="?android:attr/textAppearanceLarge"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:id="@+id/Title" />
            <TextView
                android:text="Small Text"
                android:textAppearance="?android:attr/textAppearanceSmall"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:id="@+id/DueDate" />
        </LinearLayout>
    </LinearLayout>
</RelativeLayout>

2 个答案:

答案 0 :(得分:1)

尝试在更新项目后调用适配器上的NotifyDataSetChanged(),Android中的AFAIK ListView不会观察到ObservableCollection的更改:

试试这段代码:

    button.Click += delegate {                
        allTasksCollection.Add(new UserTask("Task number " + count));
        button.Text = string.Format("{0} tasks!", count++);
        adapter.NotifyDataSetChanged();
    };

您还可以尝试在ObservableCollection中添加一个litener,在适配器中,将构造函数更改为:

this.list.CollectionChanged += (sender,args) => { NotifyDataSetChanged(); };

答案 1 :(得分:0)

查看INotifyPropertyChanged界面。它将警告列表视图列表视图中对象内的变量已更改。

https://developer.xamarin.com/guides/xamarin-forms/xaml/xaml-basics/data_bindings_to_mvvm/

编辑:误读了您的问题。我的坏。