2017-06-05 20 views
0

我有一個Xamarin Android應用程序,我試圖用複選框來呈現選項列表並獲得意外的結果。我正在適配器的GetView方法中創建一個lambda事件處理程序。我希望通過這樣做,當前調用GetView的當前項目將是調用CheckedChanged事件時引用的項目。我的代碼是:在AlertDialog中的ListView中捕獲CheckChanged事件

[Activity(Label = "ListViewCheckBox", MainLauncher = true, Icon = "@drawable/icon")] 
public class MainActivity : Activity 
{ 
    public class Item 
    { 
     public string Name { get; set; } 
     public bool Checked { get; set; } 
    } 

    List<Item> Items; 

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

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

     CreateItems(); 
    } 

    private void CreateItems() 
    { 
     Items = new List<Item>(); 

     for (int i = 0; i < 30; i++) 
     { 
      Item Item = new Item(); 
      Item.Name = "Question " + i.ToString(); 
      Items.Add(Item); 
     } 
    } 

    [Export("onButtonClicked")] 
    public void onButtonClicked(View view) 
    { 
     switch (view.Id) 
     { 
      case Resource.Id.btnShowDialog: 
       ShowDialog(); 
       break; 
     } 
    } 

    private void ShowDialog() 
    { 
     AlertDialog dlgList = (new AlertDialog.Builder(this)).Create(); 
     dlgList.SetTitle("Questions"); 
     var viewAD = this.LayoutInflater.Inflate(Resource.Layout.DialogList, null); 

     ListView lvItems = viewAD.FindViewById<ListView>(Resource.Id.lvDialog); 

     QuestionAdapter adItems = new QuestionAdapter(Items, this); 
     lvItems.Adapter = adItems; 

     dlgList.SetView(viewAD); 
     dlgList.SetButton("Close", delegate { }); 
     dlgList.Show(); 
    } 

    public class QuestionAdapter : BaseAdapter 
    { 
     private Activity context; 
     private List<Item> _Items; 

     public QuestionAdapter(List<Item> Questions, Activity context) 
     { 
      this.context = context; 
      _Items = Questions; 
     } 

     // How many items are in the data set represented by this Adapter. 
     public override int Count 
     { 
      get { return _Items.Count; } 
     } 

     // Get the data item associated with the specified position in the data set. 
     public override Java.Lang.Object GetItem(int position) 
     { 
      return position; 
     } 

     // Get the row id associated with the specified position in the list. 
     public override long GetItemId(int position) 
     { 
      return position; 
     } 

     // Get a View that displays the data at the specified position in the data set. 
     // You can either create a View manually or inflate it from an XML layout file. 
     public override View GetView(int position, View convertView, ViewGroup parent) 
     { 

      Item Item = _Items[position]; 

      if (convertView == null) 
      { 
       convertView = context.LayoutInflater.Inflate(Resource.Layout.DialogCheckListItem, null); 
      } 

      TextView t = convertView.FindViewById<TextView>(Resource.Id.txtItem); 
      t.Text = Item.Name; 

      CheckBox c = convertView.FindViewById<CheckBox>(Resource.Id.chkItem); 
      c.Checked = Item.Checked; 
      c.CheckedChange += (s, e) => 
      { 
       Item.Checked = e.IsChecked; 
      }; 

      return convertView; 
     } 
    } 
} 

如果我彈出一次警報對話框並選中幾個框並關閉它。下次我彈出它時,額外的盒子被標記爲檢查。在適配器中連接事件的正確方法是什麼,這樣當事件觸發時,它會作用於表示的基礎Item?希望有人可以看看這個,並快速指出我的錯誤,如果沒有,我有一個工作解決方案發布在這裏,你可以看到結果。 https://github.com/JimWilcox3/ListViewCheckBox

回答

0

當一個列表視圖回收視圖時,所有監聽器也附加到它。因此,如果複選框被選中並且具有CheckedChange,則兩者都將保留爲基於位置的回收視圖的一部分。所以我重置chackedChange加入c.SetOnCheckedChangeListener(null);下面這段代碼應該爲你工作:

c.SetOnCheckedChangeListener(null); 
      t.Text = Item.Name; 
      c.Checked = Item.Checked; 
      c.CheckedChange += (s, e) => 
      { 
       CheckBox checkBox = (CheckBox)s; 
       if (checkBox.Checked) 
        Item.Checked = true; 
       else 
        Item.Checked = false; 
      }; 

而且儘量避免再次創造適配器並再次所以總是在打開的對話框中其他30個項目被添加excpet如果SI你真的很想。和第一項有關的bug也是如此。