簡體   English   中英

將帶有圖像的選定 datagridview 行傳輸到另一個 datagridview

[英]transfer selected datagridview row with image to another datagridview

我正在嘗試制作購物車,當用戶在產品表中選擇行時,輸入數量並單擊“添加到購物車”,該行將轉到購物車表。 我可以做到,但圖像列顯示圖像的 system.byte 讀取。 此外,當我選擇新產品並將新產品添加到購物車時,購物車表中的前一行被覆蓋而不是添加新產品。

 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();
            }
        }
    }

}

這是圖像。 任何幫助是appreaciated 謝謝在此處輸入圖片說明

但是,為了簡單起見,我有幾個問題,一個問題是似乎沒有必要在用戶每次單擊“保存到購物車”按鈕時為第二個(選定項目)網格“重新創建”一個新的DataTable

此外,發布的代碼只是“覆蓋”了“選定”項目網格中的現有數據。 這是一種奇怪的行為。 例如,用戶單擊一個項目,然后單擊保存到購物車按鈕。 這會將項目保存在所選項目網格中,然后用戶單擊不同的項目,然后單擊保存按鈕……然后,使用已發布的項目,先前保存的項目將消失。 我猜你不想要這種行為。

鑒於上述評論和有限的發布代碼,我建議使用兩個不同的DataTables的簡單解決方案。 一張表保存“所有”項目,供用戶選擇。 顯然,它開始時填充了所有項目。 第二個表是一個“空”表,用於保存用戶選擇的項目。

我們顯然可以“手動”創建選定項目表,但是,這需要更多的工作,我們需要確保維護某些列。 “克隆”第一個表將有助於查找行並將行從一個表復制到另一個表。 換句話說,我們希望能夠查看“已選擇”項目表並查看當前選擇的項目是否已經在其中。 如果是,我們不想添加新行,我們只想更新現有選定項目的數量。

鑒於此,第二個表的模式可以使用與第一個表相同的模式,只顯示我們想要的列,或者在這種情況下……“添加”一個新的數量列。 如果我們Clone第一個表模式,然后向其中添加“數量”列,那么搜索和復制將容易得多。 這將起作用,您可以在不手動將列添加到網格的情況下執行此操作。 這意味着即使我們向第二個表添加了另一列,行導入仍然會成功。

下面是一個完整的例子,測試數據使用一個原始表格,每單位包含“ItemID”、“Description”和“Cost”列。 第二個表也有這些列和兩個附加列“QTY”用於數量和“TotalCost”。 “TotalCost”列是一個“Expression”列,它只是將“QTY”值乘以“Cost”值。 “總成本”值將在每次單擊按鈕時“數量”值發生變化時自動更新。 網格的前兩個全局數據表......

DataTable AllItems;
DataTable SelectedItems;

當表單加載時,我們用AllItems中的所有項目填充AllItems 然后我們將這個表模式“克隆”到SelectedItems表。 然后我們將數量列添加到SelectedItems表中。 最后將每個網格設置為正確的DataSource 就像是…

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;
}

如果需要,注釋掉的“SetSelectedItemsGridColumns”代碼用於自定義第二個網格的列。

有了這個設置,現在將所有項目的網格中的選定行“復制”到包含選定項目的網格中應該相對簡單。 應該注意的是,無論我們要搜索/查找的字段,都必須與數據庫中的字段類型匹配。 如果您遇到“類型”不匹配錯誤,請檢查以確保代碼中定義的“類型”與數據庫中的“類型”匹配。 在下面的示例中,我使用int的“類型”來唯一標識數據庫中的每個“ItemID”。 這對您來說顯然/可能會有所不同,您需要更改代碼以匹配您要使用的正確類型/名稱。

一、三個變量: newItemID唯一標識選中的項目。 dataRow用來自每個選定行的數據初始化。 它用於在SelectedItems表中查找行並更新現有行。 最后一個DataRowView從第一個網格中抓取所有項目的行。

通過所選行的簡單循環。 抓取選定的行並獲取其唯一的項目 ID。 從數量文本框中解析數量值。 嘗試從所選項目表中獲取行。 如果返回的行為空,則該項目不在表中,我們需要將其添加為新行。 如果返回了一行,那么我們只想將“數量”值添加到現有行中。

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;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM