Val Okafor
Val Okafor

Reputation: 3437

Checkbox Click Event Handler Called Twice

For some reason, my Checkbox.Click event handler get called twice in my Custom ListView adapter of Xamarin.Android. I am providing my GetView method below for any help or pointer in what I am doing wrong.

public override View GetView(int position, View convertView, ViewGroup parent)
        {
            ServiceViewHolder holder = null;
            var view = convertView;

            if (view == null)
            {
                view = Context.LayoutInflater.Inflate(Resource.Layout.ListRowService, null);

                holder = new ServiceViewHolder
                {
                    Name = view.FindViewById<TextView>(Resource.Id.tvServiceName),
                    Price = view.FindViewById<TextView>(Resource.Id.tvServicePrice),
                    SelectCheckbox = view.FindViewById<CheckBox>(Resource.Id.checkboxAdd)                    
                };

                view.Tag = holder;
            }
            else
            {
                    holder = view.Tag as ServiceViewHolder;
            }

            var tempServiceItem = ServiceItems[position];
            holder.Name.Text = tempServiceItem.Name;            
            holder.SelectCheckbox.Click += (o, e) =>
            {
                if (holder.SelectCheckbox.Checked)
                {
                    var myActivity = (ServicesListActivity) Context;
                    myActivity.OnServiceSelected(tempServiceItem, true);
                }
                else
                {
                    var myActivity = (ServicesListActivity) Context;
                    myActivity.OnServiceSelected(tempServiceItem, false);
                }
            };
            return view;
        }

       private class ServiceViewHolder : Java.Lang.Object
        {
            public TextView Name { get; set; }
            public TextView Price { get; set; }
            public CheckBox SelectCheckbox { get; set; }
        }

And just to clarify, the goal of this Checkbox.Click event handler it to pass the selected Item to the Activity, which it does but then it calls itself again for each click after the first click.

Upvotes: 0

Views: 1258

Answers (2)

Val Okafor
Val Okafor

Reputation: 3437

Per this Xamarin Forum post http://forums.xamarin.com/discussion/comment/27030/#Comment_27030 I realized that I was calling the Checkbox event handler twice so I re-factored it to be only called once like so.

if (convertView == null)
            {
               convertView = Context.LayoutInflater.Inflate(Resource.Layout.ListRowService, null);

                holder = new ServiceViewHolder
                {
                    Name = convertView.FindViewById<TextView>(Resource.Id.tvServiceName),
                    Price = convertView.FindViewById<TextView>(Resource.Id.tvServicePrice),
                    Category = convertView.FindViewById<TextView>(Resource.Id.tvServiceCategory),
                    EditButton = convertView.FindViewById<ImageButton>(Resource.Id.buttonEditService),
                    DeleteButton = convertView.FindViewById<ImageButton>(Resource.Id.buttonDeleteService),
                    SelectCheckbox = convertView.FindViewById<CheckBox>(Resource.Id.checkboxAdd)

                };

                holder.SelectCheckbox.Click += (o, e) => mFragment.OnServiceSelected(tempServiceItem, holder.SelectCheckbox.Checked);

                convertView.Tag = holder;
            }
            else
            {
                holder = (ServiceViewHolder)convertView.Tag;
            }

            //var tempServiceItem = new ServiceItem();
            holder.Name.Text = tempServiceItem.Name;
            holder.Category.Text = tempServiceItem.Category;
            holder.Price.Text = String.Format("{0:C}", tempServiceItem.Price);
            holder.DeleteButton.Click += (object sender, EventArgs e) =>
            {
                ServiceItems.Remove(tempServiceItem);
                ServicesManager.DeleteServiceItem(tempServiceItem.Id);

                //Then refresh the screen to show the item has been removed
                NotifyDataSetChanged();

            };
            holder.EditButton.Click += (object sender, EventArgs e) =>
            {

            };

Upvotes: 0

msolvaag
msolvaag

Reputation: 66

Are you sure GetView is only called once? If not, the click event binding would stack. Move the click event binding or ensure its only bound once.

public override View GetView(int position, View convertView, ViewGroup parent)
    {
        ServiceViewHolder holder = null;
        var view = convertView;

        if (view == null)
        {
            view = Context.LayoutInflater.Inflate(Resource.Layout.ListRowService, null);

            holder = new ServiceViewHolder
            {
                Name = view.FindViewById<TextView>(Resource.Id.tvServiceName),
                Price = view.FindViewById<TextView>(Resource.Id.tvServicePrice),
                SelectCheckbox = view.FindViewById<CheckBox>(Resource.Id.checkboxAdd)                    
            };

            view.Tag = holder;
            holder.SelectCheckbox.Tag = holder;

            holder.SelectCheckbox.Click += (o, e) =>
            {
                var h = (ServiceViewHolder)((CheckBox)o).Tag;
                var tempServiceItem = ServiceItems[h.Position];
                h.Name.Text = tempServiceItem.Name;

                if (h.SelectCheckbox.Checked)
                {
                    var myActivity = (ServicesListActivity) Context;
                    myActivity.OnServiceSelected(tempServiceItem, true);
                }
                else
                {
                   var myActivity = (ServicesListActivity) Context;
                   myActivity.OnServiceSelected(tempServiceItem, false);
                }
            };
        }
        else
        {
                holder = (ServiceViewHolder)view.Tag;
        }

        holder.Position = position;


        return view;
    }

   private class ServiceViewHolder : Java.Lang.Object
    {
        public TextView Name { get; set; }
        public TextView Price { get; set; }
        public CheckBox SelectCheckbox { get; set; }
        publit int Position{get;set;}
    }

Upvotes: 1

Related Questions