C# - Editing Listbox Items

1.4k Views Asked by At

I'm making an app in Windows Forms that simulates a Point of Sales. I'm creating now the part where the user clicks on a product button and it adds to a listbox an item like this: "'Quantity' - 'Name of the product' - 'cost'".

When the button is clicked again is supposed to edit the item like this: "'Quantity+1' - 'Name of the product' - 'cost*2'". However it just add another item with that information.

So far, my code is the following:

private void bprod1_Click(object sender, EventArgs e)
    {            
        MySqlCommand cmdp1 = new MySqlCommand("SELECT preco_unitario FROM produtos where designacao='" + bprod1.Text + "';", mConn);
        mConn.Open();
        MySqlDataReader drp1 = cmdp1.ExecuteReader();
        drp1.Read();
        string getpreco1 = drp1["preco_unitario"].ToString();
        mConn.Close();
        quant1 = quant1 + 1;
        var preco1tot = quant1 * Convert.ToDecimal(getpreco1);
        var text1 = quant1.ToString() + " - " + bprod1.Text + " - " + preco1tot.ToString();
        listvenda.Items.Add(text1);            
    }

bprod1 is my button. quant1 starts with value 0. getpreco1 is the value I get from the database (product's cost).

My objective is, when clicked the second time and so on, increase the quantity and add the cost without creating a new item. I could just delete the item and add another one with the new info, but I want the item to be in the same place as the other, and not on the end of the list.

I appreciate any suggestions and help. Hope you guys understand what I intend to do.

2

There are 2 best solutions below

2
CDove On

This line:

  listvenda.Items.Add(text1);            

is why you're seeing a new item every single time. A mature application would be more likely to use either private class or Model approaches.

Create a new class file within the same namespace and call it something. See below:

public class myProduct
{
    public int Quantity {get; set;}
    public int Name     {get; set;}
    public double Price {get; set;}

    public myProduct(string name)
    { 
      this.Quantity = 1; this.Name = name; this.Price = 0;
    }
    public override string ToString()
    {
      return this.Quantity.ToString() + "-" + this.Name + "-" + 
             (this.Price * this.Quantity).ToString(c, 
             CultureInfo.CurrentCulture);
    }
}

Now, where you were just adding values, you can check to see if the line exists, and if it does, operate on it. Otherwise, add a new line. Don't bother with ToString() methods and such, as you can actually populate your listbox with a list of the new class! It will call the ToString() method when displaying values.

List<myProduct> listvendaBind = new List<myProduct>();

///insert code here to build your list from the database if you havent already.  Otherwise, skip this step so you dont overwrite your list

//now the code for modification
var x = listvendaBind.Where(t => t.Name == newProduct.Name).FirstOrDefault();

  if(x.Count() > 0 && (x != null)
         listvendaBind[listvendaBind.IndexOf(x[0])].Quantity++;
  else
         listvendaBind.Add(newProduct);

  listvenda.DataSource = listvendaBind;

This is untested, as I'm working on another project at the moment, but should serve as proof of concept.

3
Logman On

This is only for learning and I do not recommended using it outside testing environment but you can do something like this:

insetad of

listvenda.Items.Add(text1);

do this:

bool notFound = true;
for(int i=0; i<listvenda.Items.Count; i++)
{ 
    if(((string)listvenda.Items[i]).Contains(" - " + bprod1.Text + " - "))
    {
        listvenda.Items[i] = text1;
        notFound = false;
        break;
    }
}

if(notFound)
    listvenda.Items.Add(text1);

but as I said it should only be temporary solution. Instead of this use CDove solution