2016-11-24 2 views
0

Я нашел много похожих вопросов в StackOverflow, но не могу понять эту проблему.ListView не обновляется после добавления элементов в привязку ObservableCollection (Xamarin)

Я пытаюсь привязать 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> 

ответ

1

Try позвонить NotifyDataSetChanged() на адаптере после обновления его элементов, AFAIK ListView в Android не замечает изменения на ObservableCollection:

Попробуйте этот код:

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

Вы можете также попробуйте добавить литейщик к вашему ObservableCollection, в свой адаптер, измените конструктор на это:

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

Большое спасибо @Hichaam! Оба предложенных вами решения дают мне результаты, которые я искал. Я думаю, что второе, вероятно, лучшее решение, я буду использовать это. – pulekies

+0

Рад помочь. – Hichaam

0

Посмотрите на интерфейс INotifyPropertyChanged. Он будет предупреждать список, что переменные внутри объекта в списке были изменены.

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

Edit: неправильно ваш вопрос. Виноват.

+0

Да, я думаю, что объекты внутри коллекции будут им im В конце концов, INotifyPropertyChanged. Это не имеет значения для добавления/удаления вещей из коллекции, хотя ... из того, что я понимаю, ObservableCollection должен обрабатывать это. – pulekies

+0

@pulekies Это правильно. Список должен видеть их. Я посмотрю на это позже, может быть, смогу помочь. – wasted