Link to home
Start Free TrialLog in
Avatar of SniperCode Sheva
SniperCode Sheva

asked on

How to bind values from DatagridView to Item list in C# ?

Hello, I am doing a Knapsack application in C#.

In the app, i am getting the values manually.
            var items = new List<Item>(){
      new Item("Apple", 39, 40, 4),
      new Item("Banana", 27, 60, 4),
      new Item("Beer", 52, 10, 12),
      new Item("Book", 30, 10, 2),
      new Item("Camera", 32, 30, 1),
      new Item("Cheese", 23, 30, 4),
      new Item("Chocolate Bar", 15, 60, 10),
      new Item("Compass", 13, 35, 1),
      new Item("Jeans", 48, 10, 1),
      new Item("Map", 9, 150, 2),
      new Item("Notebook", 22, 80, 1),
      new Item("Sandwich", 50, 160, 4),
      new Item("Ski Jacket", 43, 75, 1),
      new Item("Ski Pants", 42, 70, 1),
      new Item("Socks", 4, 50, 2),
      new Item("Sunglasses", 7, 20, 1),
      new Item("Suntan Lotion", 11, 70, 1),
      new Item("T-Shirt", 24, 15, 1),
      new Item("Tin", 68, 45, 1),
      new Item("Towel", 18, 12, 1),
      new Item("Umbrella", 73, 40, 1),
      new Item("Water", 153, 200, 1)
    };

Open in new window

How I can bind values from datagridview to the item list so that I will not put the values manually ?
Avatar of Misha
Misha
Flag of Russian Federation image

If you have already dataGridView with values, you can use this code, to get vaues from dataGridView

foreach (DataGridViewRow row in YourdataGridView.Rows) {
        YourClass cl = row.DataBoundItem as YourClass ;
        if(cl  != null)
          // do somethig, 
      }

Open in new window


Also you can use MVVM pattern to bind data (your list and your DataGridView)
Avatar of SniperCode Sheva
SniperCode Sheva

ASKER

I did this
            List<Item> items = new List<Item>();
            foreach (DataGridViewRow dr in dataGridView2.Rows)
            {
               items.Add(new Item(Convert.ToString(dr.Cells[1].Value), Convert.ToInt32(dr.Cells[3].Value), Convert.ToInt32(dr.Cells[2].Value), Convert.ToDouble(dr.Cells[0].Value)));


            }

Open in new window

But I am getting this error Unable to cast object of type 'System.DBNull' to other types....
Are you sure, that dr.Cells[1].Value, dr.Cells[2].Value, dr.Cells[3].Value is not null??
This error appear, when value, which you convert, is null.
Try something like this

new Item( dr.Cells[1].Value == DBNull.Value) ? string.Empty : dr.Cells[1].Value.ToString().......................)
Yes I am sure they are all not null
If you bind your DataGridView to a BindingList<Item>, then adding items to the DataGridView will add them to your underlying list automatically:

// setup your field
private readonly BindingList<Item> items = new BindingList<Item>();

// bind the grid to your list (on form load / button click etc)
myDataGridView.BindingSource = items;

Open in new window

Now when a user adds / edits / deletes an item from your DataGridView, your items list will automatically update.
But it is not fixing my problem :/ I still have the ERROR
I test this code. It work fine.
 public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            List<MyItem> items = new List<MyItem>();
            foreach (DataGridViewRow dr in dataGridView1.Rows)
            {
                items.Add(new MyItem(Convert.ToString(dr.Cells[0].Value), Convert.ToInt32(dr.Cells[1].Value)));


            }
        }
    }

    public class MyItem
    {
        string Name { get; set; }
        int Val1 { get; set; }

        public MyItem(string name, int val1)
        {
            Name = name;
            Val1 = val1;
        }
    }

Open in new window

Here is my full code
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.OleDb;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Knap
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            configureDataGridViewColumns();

        }
        public bool IsReusable { get { return true; } }

        public void ProcessRequest(DataGridView context)
        {
           


            List<Item> items = new List<Item>();
            foreach (DataGridViewRow dr in dataGridView2.Rows)
            {
                    //I've assumed imaginary properties ColName and ColValue in MyItem class
                    items.Add(new Item(Convert.ToString(dr.Cells[1].Value), Convert.ToInt32(dr.Cells[3].Value), Convert.ToInt32(dr.Cells[2].Value), Convert.ToDouble(dr.Cells[0].Value)));
                

            }
            
        



    //        var items = new List<Item>(){
    //  new Item("Apple", 39, 40, 4),
    //  new Item("Banana", 27, 60, 4),
    //  new Item("Beer", 52, 10, 12),
    //  new Item("Book", 30, 10, 2),
    //  new Item("Camera", 32, 30, 1),
    //  new Item("Cheese", 23, 30, 4),
    //  new Item("Chocolate Bar", 15, 60, 10),
    //  new Item("Compass", 13, 35, 1),
    //  new Item("Jeans", 48, 10, 1),
    //  new Item("Map", 9, 150, 2),
    //  new Item("Notebook", 22, 80, 1),
    //  new Item("Sandwich", 50, 160, 4),
    //  new Item("Ski Jacket", 43, 75, 1),
    //  new Item("Ski Pants", 42, 70, 1),
    //  new Item("Socks", 4, 50, 2),
    //  new Item("Sunglasses", 7, 20, 1),
    //  new Item("Suntan Lotion", 11, 70, 1),
    //  new Item("T-Shirt", 24, 15, 1),
    //  new Item("Tin", 68, 45, 1),
    //  new Item("Towel", 18, 12, 1),
    //  new Item("Umbrella", 73, 40, 1),
    //  new Item("Water", 153, 200, 1)
    //};

            int capacity = Convert.ToInt32(montant.Text);

            ItemCollection[] ic = new ItemCollection[capacity + 1];

            for (int i = 0; i <= capacity; i++) ic[i] = new ItemCollection();

            for (int i = 0; i < items.Count; i++)
                for (int j = capacity; j >= 0; j--)
                    if (j >= items[i].Weight)
                    {
                        double quantity = Math.Min(items[i].Quantity, j / items[i].Weight);
                        for (int k = 1; k <= quantity; k++)
                        {
                            ItemCollection lighterCollection = ic[j - k * items[i].Weight];
                            int testValue = lighterCollection.TotalValue + k * items[i].Value;
                            if (testValue > ic[j].TotalValue) (ic[j] = lighterCollection.Copy()).AddItem(items[i], k);
                        }
                    }

            // context.AppendText("Knapsack Capacity: " + capacity + "\r\n  Filled Weight: " + ic[capacity].TotalWeight + "\r\nFilled Value: " + ic[capacity].TotalValue + "\r\n Contents:<ul>");

            foreach (KeyValuePair<string, int> kvp in ic[capacity].Contents) {
                string[] row = new string[] { kvp.Key, kvp.Value.ToString() };
                context.Rows.Add(row); };

       

        }

        private void configureDataGridViewColumns()
        {
            DataGridViewColumnCollection columns = dataGridView1.Columns;


            DataGridViewTextBoxColumn textColumn = new DataGridViewTextBoxColumn();

            textColumn.DataPropertyName = "Designation";
            textColumn.Name = "Designation";
            textColumn.HeaderText = "Designation";
            textColumn.ValueType = typeof(char);
            textColumn.Width = 180;
            columns.Add(textColumn);

            textColumn = new DataGridViewTextBoxColumn();
            textColumn.DataPropertyName = "Quantite";
            textColumn.Name = "Quantite";
            textColumn.HeaderText = "Quantite";
            textColumn.ValueType = typeof(decimal);
            textColumn.ReadOnly = true;
            textColumn.DefaultCellStyle.Format = "N2";
            textColumn.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
            columns.Add(textColumn);


            textColumn = new DataGridViewTextBoxColumn();
            textColumn.DataPropertyName = "Prix Unitaire";
            textColumn.Name = "Prix Unitaire";
            textColumn.HeaderText = "Prix Unitaire (CFA.)";
            textColumn.ValueType = typeof(decimal);
            textColumn.ReadOnly = true;
            textColumn.DefaultCellStyle.Format = "N2";
            textColumn.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
            columns.Add(textColumn);
          

                        textColumn = new DataGridViewTextBoxColumn();
            textColumn.DataPropertyName = "Montant";
            textColumn.Name = "Montant";
            textColumn.HeaderText = "Montant (CFA.)";
            textColumn.ValueType = typeof(decimal);
            textColumn.ReadOnly = true;
            textColumn.DefaultCellStyle.Format = "N2";
            textColumn.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
            columns.Add(textColumn);

            Padding padding = dataGridView1.DefaultCellStyle.Padding;
            padding.Right = 10;
            dataGridView1.DefaultCellStyle.Padding = padding;
        }

        private class Item
        {

            public string Description;
            public int Weight;
            public int Value;
            public double Quantity;

            public Item(string description, int weight, int value, double quantity)
            {
                Description = description;
                Weight = weight;
                Value = value;
                Quantity = quantity;
            }

        }

        private class ItemCollection
        {

            public Dictionary<string, int> Contents = new Dictionary<string, int>();
            public int TotalValue;
            public int TotalWeight;

            public void AddItem(Item item, int quantity)
            {
                var a = ";";
                if (Contents.ContainsKey(item.Description)) { Contents[item.Description] += quantity; Contents[item.Description] += item.Weight; } else Contents[item.Description] = item.Weight; Contents[item.Description]= Convert.ToInt32(string.Format("{0:D2}{1}", item.Weight, quantity));
                TotalValue += quantity * item.Value;
                TotalWeight += quantity * item.Weight;
            }

            public ItemCollection Copy()
            {
                var ic = new ItemCollection();
                ic.Contents = new Dictionary<string, int>(this.Contents);
                ic.TotalValue = this.TotalValue;
                ic.TotalWeight = this.TotalWeight;
                return ic;
            }

        }

        private void button1_Click(object sender, EventArgs e)
        {
            ProcessRequest(dataGridView1);

        }

        private void button2_Click(object sender, EventArgs e)
        {
            openFileDialog1.ShowDialog();
            string nomFichier = openFileDialog1.FileName;
            //string nomFichier = My.Computer.FileSystem.CurrentDirectory + "\\ex47.xlsx";
            DataSet dat = default(DataSet);
            dat = new DataSet();
            //déclaration et utilisation d'un OLeDBConnection 
            using (OleDbConnection Conn =
                new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;"
                + " Data Source='" + nomFichier + "';"
                + " Extended Properties=\"Excel 8.0;;HDR=YES\""))
            {

                Conn.Open();

                //déclaration du DataAdapter 
                //notre requête sélectionne toute les cellule de la Feuil1 
                using (OleDbDataAdapter Adap = new OleDbDataAdapter("select * from [Feuil1$]", Conn))
                {
                    Adap.TableMappings.Add("Table", "TestTable");
                    //Chargement du Dataset 
                    Adap.Fill(dat);
                    //On charge les données sur le DGV 
                    dataGridView2.DataSource = dat.Tables[0];
                }
                //libèrer les ressources 
                Conn.Close();

            }
        }
    }

}

Open in new window

It is very strangely. I test your code, and it also works fine!
But in this code you dont populate your dataGridView. It is empty, may be problem in not correct data?
I populate my datagrid with this :
private void button2_Click(object sender, EventArgs e)
        {
            openFileDialog1.ShowDialog();
            string nomFichier = openFileDialog1.FileName;
            //string nomFichier = My.Computer.FileSystem.CurrentDirectory + "\\ex47.xlsx";
            DataSet dat = default(DataSet);
            dat = new DataSet();
            //déclaration et utilisation d'un OLeDBConnection 
            using (OleDbConnection Conn =
                new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;"
                + " Data Source='" + nomFichier + "';"
                + " Extended Properties=\"Excel 8.0;;HDR=YES\""))
            {

                Conn.Open();

                //déclaration du DataAdapter 
                //notre requête sélectionne toute les cellule de la Feuil1 
                using (OleDbDataAdapter Adap = new OleDbDataAdapter("select * from [Feuil1$]", Conn))
                {
                    Adap.TableMappings.Add("Table", "TestTable");
                    //Chargement du Dataset 
                    Adap.Fill(dat);
                    //On charge les données sur le DGV 
                    dataGridView2.DataSource = dat.Tables[0];
                }
                //libèrer les ressources 
                Conn.Close();

            }
        }
 

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of Chris Stanyon
Chris Stanyon
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I populate the data from Excel also.
I concur with Chris...  Much of the functionality you require is already built in...  The only part of your task that requires any work is the creation of the class objects which represents your datarows, retrieval of the data from the datasource (database, file; etc) and the saving of any of the data changed in the datagridview back into the orginal datasource.

Here is an example of this process which uses an XML file as it's datasource:

Form1.cs -
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using System.Xml.Serialization;

namespace EE_Q29101608
{
    public partial class Form1 : Form
    {
        List<Configuration> configurations;

        public Form1()
        {
            InitializeComponent();

            if (File.Exists("Configurations.xml"))
            {
                configurations = configurations.DerserializeFromFile("Configurations.xml").ToList();
            }
            else
            {
                if (configurations == null)
                {
                    configurations = new List<Configuration>((from i in Enumerable.Range(0, 10) select new Configuration { ID = i, Name = $"ZMDI{i}" }));
                }
                configurations.SerializeToFile("Configurations.xml");
            }
        }

        protected void OnLoad(object sender, EventArgs e)
        {
            bindingSource1.DataSource = configurations;
            dataGridView1.DataSource = bindingSource1;
        }

        protected void OnClosing(object sender, FormClosingEventArgs e)
        {
            configurations.SerializeToFile("Configurations.xml");
        }
    }

    public class Configuration
    {
        [XmlElement(ElementName = "CompanyID")]
        public int ID { get; set; }
        [XmlElement(ElementName = "CompanyString")]
        public string Name { get; set; }
        public uint Test1 { get; set; }
        public uint Test2 { get; set; }
        public uint Test3 { get; set; }
    }

    static class Extensions
    {
        public static T DerserializeFromFile<T>(this T source, string fileName) where T : class, IEnumerable, new()
        {
            try
            {
                using (var stream = new FileStream(fileName, FileMode.Open, FileAccess.Read))
                {
                    var serializer = new XmlSerializer(typeof(T));
                    return (T)serializer.Deserialize(stream);
                }
            }
            catch (Exception)
            {
                return new T();
            }
        }

        public static void SerializeToFile<T>(this T source, string fileName) where T : class, IEnumerable
        {
            try
            {
                if (File.Exists(fileName))
                    File.Delete(fileName);

                using (var stream = new FileStream(fileName, FileMode.Create, FileAccess.ReadWrite))
                {
                    var serializer = new XmlSerializer(typeof(T));
                    serializer.Serialize(stream, source);
                }
            }
            catch (Exception) {; }
        }
    }
}

Open in new window

Form1.Designer.cs -
namespace EE_Q29101608
{
    partial class Form1
    {
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.components = new System.ComponentModel.Container();
            this.dataGridView1 = new System.Windows.Forms.DataGridView();
            this.bindingSource1 = new System.Windows.Forms.BindingSource(this.components);
            ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit();
            ((System.ComponentModel.ISupportInitialize)(this.bindingSource1)).BeginInit();
            this.SuspendLayout();
            // 
            // dataGridView1
            // 
            this.dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
            this.dataGridView1.Dock = System.Windows.Forms.DockStyle.Fill;
            this.dataGridView1.Location = new System.Drawing.Point(0, 0);
            this.dataGridView1.Name = "dataGridView1";
            this.dataGridView1.RowHeadersVisible = false;
            this.dataGridView1.Size = new System.Drawing.Size(530, 295);
            this.dataGridView1.TabIndex = 0;
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(530, 295);
            this.Controls.Add(this.dataGridView1);
            this.Name = "Form1";
            this.Text = "Form1";
            this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.OnClosing);
            this.Load += new System.EventHandler(this.OnLoad);
            ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit();
            ((System.ComponentModel.ISupportInitialize)(this.bindingSource1)).EndInit();
            this.ResumeLayout(false);

        }

        #endregion

        private System.Windows.Forms.DataGridView dataGridView1;
        private System.Windows.Forms.BindingSource bindingSource1;
    }
}

Open in new window

Which produces the following output -User generated imageIf we modify the datagridview fields -User generated imageAnd close the form, we see that the xml file gets updated:
<?xml version="1.0"?>
<ArrayOfConfiguration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Configuration>
    <CompanyID>0</CompanyID>
    <CompanyString>ZMDI0</CompanyString>
    <Test1>12</Test1>
    <Test2>24</Test2>
    <Test3>36</Test3>
  </Configuration>
  <Configuration>
    <CompanyID>1</CompanyID>
    <CompanyString>ZMDI1</CompanyString>
    <Test1>0</Test1>
    <Test2>0</Test2>
    <Test3>0</Test3>
  </Configuration>
  <Configuration>
    <CompanyID>2</CompanyID>
    <CompanyString>ZMDI2</CompanyString>
    <Test1>24</Test1>
    <Test2>36</Test2>
    <Test3>48</Test3>
  </Configuration>
  <Configuration>
    <CompanyID>3</CompanyID>
    <CompanyString>ZMDI3</CompanyString>
    <Test1>0</Test1>
    <Test2>0</Test2>
    <Test3>0</Test3>
  </Configuration>
  <Configuration>
    <CompanyID>4</CompanyID>
    <CompanyString>ZMDI4</CompanyString>
    <Test1>36</Test1>
    <Test2>48</Test2>
    <Test3>60</Test3>
  </Configuration>
  <Configuration>
    <CompanyID>5</CompanyID>
    <CompanyString>ZMDI5</CompanyString>
    <Test1>0</Test1>
    <Test2>0</Test2>
    <Test3>0</Test3>
  </Configuration>
  <Configuration>
    <CompanyID>6</CompanyID>
    <CompanyString>ZMDI6</CompanyString>
    <Test1>48</Test1>
    <Test2>60</Test2>
    <Test3>72</Test3>
  </Configuration>
  <Configuration>
    <CompanyID>7</CompanyID>
    <CompanyString>ZMDI7</CompanyString>
    <Test1>0</Test1>
    <Test2>0</Test2>
    <Test3>0</Test3>
  </Configuration>
  <Configuration>
    <CompanyID>8</CompanyID>
    <CompanyString>ZMDI8</CompanyString>
    <Test1>60</Test1>
    <Test2>72</Test2>
    <Test3>84</Test3>
  </Configuration>
  <Configuration>
    <CompanyID>9</CompanyID>
    <CompanyString>ZMDI9</CompanyString>
    <Test1>0</Test1>
    <Test2>0</Test2>
    <Test3>0</Test3>
  </Configuration>
</ArrayOfConfiguration>

Open in new window

-saige-