我有一个Xamarin Android应用程序,我试图通过复选框显示选项列表并获得意外结果。我在适配器的GetView方法中创建一个lambda事件处理程序。我希望通过这样做,当前调用GetView的当前项将是调用CheckedChanged事件时引用的项。我的代码是:
[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;
}
}
}
如果我弹出警报对话框并检查几个框并关闭它。下次我弹出它时,额外的框被标记为已选中。在适配器中连接事件的正确方法是什么,以便在事件触发时,它作用于表示的基础项?希望有人可以看看这个,并快速指出我的错误,如果没有,我有一个工作解决方案发布在这里,你可以看到结果。 https://github.com/JimWilcox3/ListViewCheckBox
答案 0 :(得分:0)
当listview回收视图时,所有侦听器也会附加到视图中。因此,如果选中该复选框并且具有CheckedChange
,则两者都将基于位置保留为回收视图的一部分。所以我通过添加c.SetOnCheckedChangeListener(null);
来重置chackedChange这个代码应该适合你:
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个项目,如果那是你真正想要的东西。而且bug也与第一个项目有关。