在AlertDialog中捕获ListView中的CheckChanged事件

时间:2017-06-05 19:21:09

标签: c# android xamarin visual-studio-2015

我有一个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

1 个答案:

答案 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也与第一个项目有关。