Search code examples
androidlistviewxamarinadapter

Execute Function/Procedure from Listview item post-delete adapter in xamarin android


Sorry, I'm using google translate.

Hello, I am developing an app in xamarin android with visual studio 2017 for taking orders where I send information from a fragment to a List<EN_WishDetalle> to store the selection of items and this is dumped to an adapter to show it in another fragment.

In layout design it has 3 buttons (add quantity/decrease quantity/delete item),

the error lies when removing an item from the listview with sList.RemoveAt(position); NotifyDataSetChanged();
This is deleted and updated in the listview but when I try to execute any of the mentioned buttons again they make a double call (it is as if they were pressed twice and they execute their function twice)
all as a result of the NotifyDataSetChanged();

I have already checked it, however if I close the fragment with backspace (back) and re-enter everything works correctly until I use the delete item button again and we return to the same problem; so I thought of avoiding using it (NotifyDataSetChanged();) and looking for a way to reload the fragment's listview from the adapter without any success. I would like your support or suggestion to take the right path.

adapter:

public override View GetView(int position, View convertView, ViewGroup parent)
{
    View row = convertView;
    try
    {
        if (row == null)
        {
            row = LayoutInflater.From(sContext).Inflate(Resource.Layout.item_Wish, null, false);
        }
        TextView txtCodigo = row.FindViewById<TextView>(Resource.Id.Codigo);
        txtCodigo.Text = sList[position].codigo;
        TextView txtArticulo = row.FindViewById<TextView>(Resource.Id.Articulo);
        txtArticulo.Text = sList[position].articulo;
        EditText txtCantidad = row.FindViewById<EditText>(Resource.Id.Cantidad);
        txtCantidad.Text = sList[position].cantidad.ToString();
        TextView txtPrecio = row.FindViewById<TextView>(Resource.Id.Precio);
        txtPrecio.Text = sList[position].importetotal;
        ImageView Art = row.FindViewById<ImageView>(Resource.Id.Image);
        Art.SetImageResource(Android.Resource.Color.Transparent);
        if (sList[position].imagenproducto == "")
        {
            Art.SetImageResource(Resource.Drawable.NoDisponible);
        }
        else
        {
            Android.Net.Uri myUri = (Android.Net.Uri.Parse(sList[position].imagenproducto));
            //Art.SetImageURI(myUri);
            Art.SetImageURI(myUri);
        }

        Button buttonMax = row.FindViewById<Button>(Resource.Id.btnMax);
        Button buttonMin = row.FindViewById<Button>(Resource.Id.btnMin);
        ImageButton buttonDel = row.FindViewById<ImageButton>(Resource.Id.btnDel);

        buttonMax.Click += delegate
        {
            sList[position].cantidad = sList[position].cantidad + 1;
            txtCantidad.SetText(Convert.ToString(sList[position].cantidad), TextView.BufferType.Normal);
        };

        buttonMin.Click += delegate
        {
            sList[position].cantidad = sList[position].cantidad - 1;
            txtCantidad.SetText(Convert.ToString(sList[position].cantidad), TextView.BufferType.Normal);

        };

        buttonDel.Click += delegate
        {
            Android.App.AlertDialog.Builder dialog = new AlertDialog.Builder(sContext);
            AlertDialog alert = dialog.Create();
            alert.SetTitle("GumisaAPP");
            alert.SetMessage("Eliminar item : (" + position.ToString() + ") - " + sList[position].codigo + sList[position].articulo);
            alert.SetIcon(Resource.Drawable.Alerta);
            alert.SetButton("OK", (c, ev) =>
            {
                sList.RemoveAt(position);
                NotifyDataSetChanged();

            });
            alert.SetButton2("CANCEL", (c, ev) =>
            {

            });
            alert.Show();
            //mAlertMessageBoxOk.onOkClick(5);

        };


    }
    catch (Exception ex)
    {
        System.Diagnostics.Debug.WriteLine(ex.Message);
    }
    finally { }
    return row;
}

fragment:

private ListView WishlistView;
WishAdapter adapter;        
List<EN_WishDetalle> List_Wish = new List<EN_WishDetalle>();
       
public override View OnCreateView(LayoutInflater inflater, Android.Views.ViewGroup container, Android.OS.Bundle savedInstanceState)
{
    base.OnCreateView(inflater, container, savedInstanceState);

    //HasOptionsMenu = true;
    var view = inflater.Inflate(Resource.Layout.Main_Wish, null);

    WishlistView = view.FindViewById<ListView>(Resource.Id.List);
    EditText txtCantidad = view.FindViewById<EditText>(Resource.Id.Cantidad);

    List_Wish = Variables.WishDetalle;

    adapter = new WishAdapter(Activity, List_Wish);
    //adapter2 = new WishAdapter( ).;
    WishlistView.Adapter = adapter;

    //InputSearch = view.FindViewById<EditText>(Resource.Id.inputSearch);
    //InputSearch.TextChanged += InputSearch_TextChanged;
    //List<EN_Clientes> objstud = new List<EN_Clientes>();
    WishlistView = view.FindViewById<ListView>(Resource.Id.List);

    Button buttonMax = view.FindViewById<Button>(Resource.Id.btnMax);
    Button buttonMin = view.FindViewById<Button>(Resource.Id.btnMin);
    ImageButton buttonDel = view.FindViewById<ImageButton>(Resource.Id.btnDel);

    WishlistView.ItemClick += buttonMax_ItemClick;
    //WishlistView.ItemClick += buttonMin_ItemClick;
    //WishlistView.ItemClick += buttonDel_ItemClick;

    return view;
}

void buttonMax_ItemClick(object sender,AdapterView.ItemClickEventArgs e)
{
    
}
void buttonMin_ItemClick(object sender, AdapterView.ItemClickEventArgs x)
{

}
void buttonDel_ItemClick(object sender, AdapterView.ItemClickEventArgs z)
{

}

Also indicate that I have a class with the variable List<EN_WishDetalle> in public to be able to store the information in memory and avoid using the database.

public static List<EN_WishDetalle> WishDetalle = new List<EN_WishDetalle>();

enter image description here

enter image description here


Solution

  • Because of ListView's recycling mechanism, you can use ViewHolder and button Tag to achieve this.

    Based on your code, I created a simple demo, it works on my side for Button buttonDel.

    You can refer to the following code:

    public override View GetView(int position, View convertView, ViewGroup parent)
    {
        var item = items[position];
    
        View view = convertView; // re-use an existing view, if one is available
        MyViewHolder holder;
    
    
            if (view != null)
            {
                holder = view.Tag as MyViewHolder;
    
                holder.buttonDel.Tag = position;
                //holder.buttonMax.Tag = position;
                //holder.buttonMin.Tag = position;
            }
            else
            { // otherwise create a new one
                holder = new MyViewHolder();
    
                LayoutInflater inflater = (LayoutInflater)context.GetSystemService(Context.LayoutInflaterService);
                view = inflater.Inflate(Resource.Layout.CustomView, null);
    
                holder.HeadingTextView = view.FindViewById<TextView>(Resource.Id.Text1);
                holder.SubHeadingTextView = view.FindViewById<TextView>(Resource.Id.Text2);
                holder.IconImage = view.FindViewById<ImageView>(Resource.Id.Image);
    
    
                holder.buttonMax = view.FindViewById<Button>(Resource.Id.btnMax);
                holder.buttonMin = view.FindViewById<Button>(Resource.Id.btnMin);
                holder.buttonDel = view.FindViewById<ImageButton>(Resource.Id.btnDel);
    
    
                holder.buttonMax.Click += delegate
                {
    
                };
    
                holder.buttonMin.Click += delegate
                {
    
    
                };
    
                holder.buttonDel.Click += delegate
                {   // we get the tag here for  buttonDel
                    int position = (int)holder.buttonDel.Tag;
    
                    Android.App.AlertDialog.Builder dialog = new AlertDialog.Builder(context);
                    AlertDialog alert = dialog.Create();
                    alert.SetTitle("GumisaAPP");
                    alert.SetMessage("Eliminar item : (" + position.ToString() + ") - " + items[position].Heading + items[position].SubHeading);
                    alert.SetIcon(Resource.Drawable.love);
                    alert.SetButton("OK", (c, ev) =>
                    {
                        items.RemoveAt(position);
                        NotifyDataSetChanged();
    
                    });
                    alert.SetButton2("CANCEL", (c, ev) =>
                    {
    
                    });
                    alert.Show();
    
                };
    
    
                holder.buttonDel.Tag = position;
                view.Tag = holder;
            }
    
    
            holder.HeadingTextView.Text = item.Heading;
            holder.SubHeadingTextView.Text = item.SubHeading;
            holder.IconImage.SetImageResource(item.ImageResourceId);
    
    
            return view;
    }
    
    
    
        public class MyViewHolder : Java.Lang.Object
        {
            public TextView HeadingTextView { get; set; }
            public TextView SubHeadingTextView { get; set; }
    
            public ImageView IconImage { get; set; }
    
    
            public Button buttonMax { get; set; }
    
            public Button buttonMin { get; set; }
            public ImageButton buttonDel { get; set; }
    
        }