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.
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)
};
How I can bind values from datagridview to the item list so that I will not put the values manually ?
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)));
}
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 ()........ .......... .....)
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
ASKER
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;
Now when a user adds / edits / deletes an item from your DataGridView, your items list will automatically update.
ASKER
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;
}
}
ASKER
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();
}
}
}
}
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?
But in this code you dont populate your dataGridView. It is empty, may be problem in not correct data?
ASKER
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();
}
}
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
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 -
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) {; }
}
}
}
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;
}
}
Which produces the following output -If we modify the datagridview fields -And 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>
-saige-
Open in new window
Also you can use MVVM pattern to bind data (your list and your DataGridView)