【问题标题】:ListView not updating after elements added to bound ObservableCollection (Xamarin)将元素添加到绑定的 ObservableCollection (Xamarin) 后 ListView 未更新
【发布时间】:2016-11-24 06:23:13
【问题描述】:

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

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

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

活动代码

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>

【问题讨论】:

    标签: android listview xamarin observablecollection


    【解决方案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(); };
    

    【讨论】:

    • 非常感谢@Hichaam!您提供的两种解决方案都给了我想要的结果。我认为第二个可能是更好的解决方案,我会使用它。
    • 很高兴它有帮助。
    【解决方案2】:

    看一下 INotifyPropertyChanged 接口。它将警告列表视图列表视图中对象内的变量已更改。

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

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

    【讨论】:

    • 是的,我认为集合中的对象最终必须实现 INotifyPropertyChanged。不过,从集合中添加/删除东西应该没关系..据我所知, ObservableCollection 应该处理这个。
    • @pulekies 这是正确的。列表视图应该看到它们。稍后我会再看一遍,也许我能帮上忙。
    猜你喜欢
    • 2016-10-03
    • 2018-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-23
    • 1970-01-01
    • 2012-05-26
    相关资源
    最近更新 更多