transfer selected datagridview row with image to another datagridview

311 views Asked by At

I am trying to make a cart and when user select row in product table, enter quantity and click "add to cart" the row will go to the cart table. i can do it but the image column shows the system.byte insread of the image. also when i select new product and add new it to cart, the previous row in cart table got overwritten instead of adding the new one.

 public partial class AddToCartForm : Form
{
    public AddToCartForm()
    {
        InitializeComponent();
    }

    private void AddToCartForm_Load(object sender, EventArgs e)
    {
        PopulateProductImageDgv("Select * from ProductDetailsTwo", ref dataGridView1);

        dataGridView1.MultiSelect = false;
        dataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect;

        dataGridView2.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
        dataGridView2.RowTemplate.Height = 100;
        dataGridView2.AllowUserToAddRows = false;

    }

    private void btnSaveToCart_Click(object sender, EventArgs e)
    {
        if (dataGridView1.SelectedRows.Count > 0)
        {
            DataTable dt = new DataTable();
            dt.Columns.Add("Id");
            dt.Columns.Add("Name");
            dt.Columns.Add("ImageData");
            dt.Columns.Add("Qty");
            foreach (DataGridViewRow dgvRow in dataGridView1.SelectedRows)
            {
                dt.Rows.Add(dgvRow.Cells[0].Value, dgvRow.Cells[1].Value, dgvRow.Cells[2].Value, txtqty.Text.ToString());
            }

            dataGridView2.DataSource = dt;

        }
        else
        {
            MessageBox.Show("select something");
        }
    }

    public void PopulateProductImageDgv(string sql, ref DataGridView dg)
    {
        using (SqlConnection connection = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["cn"].ConnectionString))
        {
            connection.Open();

            using (SqlCommand cmd = new SqlCommand(sql, connection))
            {
                SqlDataAdapter da = new SqlDataAdapter(cmd);
                DataTable table = new DataTable();

                //settings for dgv with image
                dg.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
                dg.RowTemplate.Height = 100;
                dg.AllowUserToAddRows = false;

                da.Fill(table);
                dg.DataSource = table;

                DataGridViewImageColumn imageColumn = new DataGridViewImageColumn();
                imageColumn = (DataGridViewImageColumn)dg.Columns[2];
                imageColumn.ImageLayout = DataGridViewImageCellLayout.Stretch;

                connection.Close();
            }
        }
    }

}

here is the image. any help is appreaciated thanks enter image description here

1

There are 1 answers

0
JohnG On

There are a few questions I have, however, to keep it simple, one issue is it appears unnecessary to “recreate” a new DataTable for the second (selected items) grid every time the user clicks the save to cart button.

In addition, the posted code simply “overwrites” the existing data in the “selected” items grid. This is an odd behavior. Example, the user clicks an item, then, clicks the save to cart button. This will save the item in the selected items grid, then the user clicks a different item, then clicks the save button… THEN, using the posted, the previously saved item will go away. I am guessing you do not want this behavior.

Given the above comments and the limited posted code, I suggest a simple solution using two different DataTables for this. One table keeps “all” the items and is used for the user to select from. It obviously starts out populated with all the items. The second table is an “empty” table that is used to hold the items selected by the user.

We could obviously “manually” create the selected items table, however, that requires more work and we would need to make sure that certain columns are maintained. "Cloning" the first table will help finding and copying rows from one table to another. In other words, we want to be able to look in the “selected” items table and see if the currently selected item is already in there. If it is, we don’t want to add a new row, we simply want to update the quantity for the existing selected item.

Given this, the second table’s schema could use the same schema as the first table and only display the columns we want, or in this case… “add” a new quantity column. If we Clone the first tables schema then add the “quantity” column to it, then, searching and copying will be much easier. This will work, and you could do this without manually adding the columns to grid. Meaning that even though we added another column to the second table the row import will still succeed.

A complete example is below, the test data uses an original table with columns “ItemID”, “Description” and “Cost” per unit. The second table, also has those columns and two additional columns “QTY” for the quantity and “TotalCost.” The “TotalCost” column is an “Expression” column that simply multiplies the “QTY” value times the “Cost” value. “TotalCost” values will be updated automatically when the “qty” values changes with each button click. First two global data tables for the grids…

DataTable AllItems;
DataTable SelectedItems;

When the form loads, we fill AllItems with all the items from the DB. Then we “clone” this table schema to the SelectedItems table. Then we add the quantity column to the SelectedItems table. And finally set each grid to the proper DataSource. Something like…

private void Form3_Load(object sender, EventArgs e) {
  AllItems = GetDataFromDB();
  SelectedItems = AllItems.Clone();
  DataColumn qtyCol = new DataColumn();
  qtyCol.ColumnName = "QTY";
  qtyCol.DataType = typeof(int);
  SelectedItems.Columns.Add(qtyCol);
  DataColumn totCol = new DataColumn();
  totCol.ColumnName = "Tot";
  totCol.DataType = typeof(decimal);
  totCol.Expression = "Cost * QTY";
  SelectedItems.Columns.Add(totCol);
  //SetSelectedItemsGridColumns();
  dataGridView1.DataSource = AllItems;
  dataGridView2.DataSource = SelectedItems;
}

The commented out ‘SetSelectedItemsGridColumns` code is used to customize the second grid’s columns if needed.

With this set up, now it should be relatively simple to “copy” the selected rows from the grid with all the items to the grid with the selected items. It should be noted that whatever field we want to search by/find by, must match the field type from the DB. If you get “type” mismatch errors, check to make sure the “type” defined in the code matches the “type” from the DB. In the example below, I use a “type” of int to uniquely identify each “ItemID” in the DB. This will/may obviously be different for you and you will need to change the code to match the proper type/name you want to use.

First, three variables: newItemID to uniquely identify the selected item. And dataRow which is initialized with the data from each selected row. It is used to find the row in the SelectedItems table and also to update existing rows. Lastly a DataRowView to grab the row from the first grid with all the items.

A simple loop through the selected rows. Grab the selected row and get its unique item id. Parse the quantity value from the quantity text box. Try and get the row from the selected items table. If the returned row is null, then the item is not in the table and we need to add it as a new row. If a row IS returned, then we want to simply add the “quantity” value to the existing row.

private void button1_Click(object sender, EventArgs e) {
  int newItemID;
  DataRow dataRow;
  DataRowView drv;
  foreach (DataGridViewRow dgr in dataGridView1.SelectedRows) {
    drv = (DataRowView)dgr.DataBoundItem;
    newItemID = (int)drv["ItemID"];
    int.TryParse(txtQTY.Text.Trim(), out int qty);
    dataRow = SelectedItems.AsEnumerable().Where(x => x.Field<int>("ItemID") == newItemID).FirstOrDefault();
    if (dataRow != null) {
      int tot = (int)dataRow["QTY"] + qty;
      dataRow["QTY"] = tot;
    }
    else {
      SelectedItems.ImportRow(drv.Row);
      dataRow = SelectedItems.AsEnumerable().Where(x => x.Field<int>("ItemID") == newItemID).FirstOrDefault();
      dataRow["QTY"] = qty;
    }
  }
}

private DataTable GetDataFromDB() {
  DataTable dt = new DataTable();
  dt.Columns.Add("ItemID", typeof(int));
  dt.Columns.Add("Description", typeof(string));
  dt.Columns.Add("Cost", typeof(decimal));
  Random rand = new Random();
  for (int i = 1; i < 10; i++) {
    dt.Rows.Add(i, "Item_" + i, rand.NextDouble() * 100);
  }
  return dt;
}