2016-11-24 21 views
0

StackOverflowに関する多くの類似の質問がありましたが、この問題を把握していないようです。バインドされたObservableCollection(Xamarin)に追加された要素の後にリストビューが更新されない

ObservableCollectionをListViewにバインドしようとしているので、コレクションの内容が変更されたときにListViewが自動的に更新されるようにしています。残念ながら、要素がコレクションに(ボタンクリックによって)追加されると、ListViewは更新されていません。 ListViewにコレクションの現在の内容を反映させるにはどうすればよいですか?

注:レイアウトを強制的にlistView.RequestLayout();とすると、listViewには正しい数の項目が含まれているようです。ただし、必ずしもの右アイテムは含まれません。たとえば、最初のアイテムを削除して最後に新しいアイテムを追加すると、レイアウトを強制することは効果がありません。最初のアイテムを削除した後にレイアウトを強制し、最後に1つ追加した後は、内容は正しいです。

アクティビティコード

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

てみてください、そのアイテムを更新した後、あなたのアダプタのNotifyDataSetChanged()を呼び出すために、Androidの中に私の知る限りのListViewは、あなたのObservableCollectionの変化を観察しません。 ObservableCollectionにリセナーを追加しようとすると、コンストラクタが次のように変更されます。

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

ありがとう@Hichaam!あなたが提供した両方のソリューションは、私が探していた結果を私に提供します。私は、2番目の方がおそらく良い解決策だと思います。私はそれを使用します。 – pulekies

+0

喜んで助けました。 – Hichaam

0

はINotifyPropertyChangedインターフェイスを見てみましょう。リストビュー内のオブジェクト内の変数が変更されたことを、リストビューに警告します。

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

編集:あなたの質問を読み違えます。私の悪い。

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

次の操作も実行できます。

は、このコードを試してみてください。

+0

はい、コレクション内のオブジェクトはim最終的にINotifyPropertyChangedを実装します。しかし、ObservableCollectionがこれを処理する必要があると私が理解しているものから、コレクションに追加/削除することは問題ではありません。 – pulekies

+0

@pulekiesこれは正しいです。リストビューに表示されます。私はこれを後でもう一度見ていきますが、おそらく私は助けることができます。 – wasted

関連する問題