i imported my data from Excel sheet to grid view.after that i want to put the column header text of my grid view into drop down,but i can't access them
help me plz :-( ;
this is my code but it dose not work :
List<string> lst = new List<string>();
* for (int i = 0; i < dg_excel.Columns.Count; i++)
{
lst.Add(dg_excel.Columns[i].HeaderText);
}
ddl_prd_count.DataSource;
ddl_prd_count.DataBind();
for this * line it says to me there are no columns (column.count = 0)
Check answer on another SO thread Why column count is 0 for GridView to know that why are you not able to access the columns from your grid's Columns collection.
In my opinion, if you want to use auto generated columns then follow this ASP.net forum link - Customizing Auto Generated Columns (GridView) and SO thread How to hide columns in an ASP.NET GridView with auto-generated columns?.
e.g.
have an idea from this code.. i have not checked the proper syntax etc in it.
protected void MyGridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.Header)
{
if (IsFillCombo)
{
//fill your list here.
for (int i = 0; i < datasourcetable.Columns.Count; i++)
{
lst.Add(e.Row.Cells[i].Text);
}
IsFillCombo = false;
}
}
}
// Another simplest way to implement this as below: From Question Text
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
List<Abc> listofAbc = new List<Abc>();
for (int i = 0; i < 10; i++)
{
listofAbc.Add(new Abc
{
ID = i + 1,
Name = "Abc" + (i + 1).ToString()
});
}
GridView1.DataSource = listofAbc;
GridView1.DataBind();
List<string> lst = new List<string>();
for (int i = 0; i < GridView1.HeaderRow.Cells.Count; i++)
{
lst.Add(GridView1.HeaderRow.Cells[i].Text);
System.Diagnostics.Debug.WriteLine(GridView1.HeaderRow.Cells[i].Text);
}
}
}
}
public class Abc
{
public int ID { get; set; }
public string Name { get; set; }
}
you can use following code
List<string> lst = new List<string>();
for (int i = 0; i < dg_excel.HeaderRow.Cells.Count; i++)
{
lst.Add(dg_excel.HeaderRow.Cells[i].Text);
}
ddl_prd_count.DataSource=lst ;
ddl_prd_count.DataBind();
Access gridView1_CellValueChanged event of your grid
and then accesse.Column.FieldName.ToString()
Related
I have two datagridviews. datagridview1 and datagridview2. When I add a product from datagridview1 to datagridview2 the quantity of the product in datagridview1 is transferred to datagridview2. Now when I remove a product from datagridview2 I need it to transfer the quantity back to datagridview1.
Here is my code.:
private void btnRemove_Click(object sender, EventArgs e)
{
int ind = findIndexForItem(dgvPOScart.CurrentRow.Cells[0].Value.ToString());
int dgvCARTquantity = Convert.ToInt32(dgvPOScart.CurrentRow.Cells[4].Value.ToString());
int dgvPOSquantity = Convert.ToInt32(dgvPOScart.Rows[ind].Cells[5].Value.ToString());
int dgvnewADDquantity;
dgvnewADDquantity = dgvPOSquantity + dgvCARTquantity;
foreach (DataGridViewRow item in this.dgvPOScart.SelectedRows)
{
dgvPOScart.Rows.RemoveAt(item.Index);
}
}
And the code for the helper:
private int findIndexForItem(string name)
{
int ind = -1;
for (int i = 0; i < dgvPOSproduct.Rows.Count; i++)
{
if (dgvPOSproduct.Rows[i].Equals(name))
{
ind = i;
break;
}
}
return ind;
}
How can I properly call ind? Rows[ind] is wrong because ind is the product ID or value or cell[0] and not row index. Or is there an easier way to do this?
Your code is a little weird, you are foreach-ing the SelectedRows but you're only calculating the new quantity for the current row, why?
Also, you shouldn't look at the products by their name since you have their ID (which is more unique than a name).
In order for this to work, you'll need something like this:
private void btnRemove_Click(object sender, EventArgs e)
{
foreach (var row in dgvPOScart.SelectedRows)
{
// Get the row in dgvProducts and the quantity he'll gain back
var productRow = dgvPOSproduct.Rows[FindRowIndexByID(row.Cells[0].Value)];
int qtyToAdd = Convert.ToInt32(row.Cells[4].Value);
// Add the quantity back
productRow.Cells[5].Value = Convert.ToInt32(productRow.Cells[5].Value) + qtyToAdd;
}
}
private int FindRowIndexByID(string id)
{
for (int i = 0; i < dgvPOSproduct.Rows.Count; i++)
{
if (dgvPOSproduct.Rows[i].Cells[0].Value == id)
{
return i;
}
}
return -1;
}
I have a task to develop Windows applications where paging is involved. If I perform any event like splitting date and time, it's applied only to the current page. I would like to apply that event to all pages in the Datagridview.
If I take a datatable/dataset and work on it, the UI is taking time to read the file as it again reads the whole file to data table. So, please suggest any other alternative to apply the events to all pages in the DataGridView.
I will post the code, or upload my code in any site or here, if required.
Please let me know if my question is unclear.
VARIABLES DECLARATION:
List<String> cmbList = new List<string>();
public String Replace;
public String Find;
public String Col;
public String NewColumn;
public String NewColumnValue;
public string MyFOrmat { get; set; }
int PageCount;
int maxRec;
int pageSize = 30;
int currentPage = 1;
int recNo = 0;
string FileName;
String[] datfile;
button1 = BROWSE BUTTON (Where i read the file):
private void button1_Click(object sender, EventArgs e)
{
OpenFileDialog openFileDialog1 = new OpenFileDialog();
openFileDialog1.InitialDirectory = "Desktop";
openFileDialog1.Filter = "dat files (*.DAT)|*.DAT|All files (*.*)|*.*";
openFileDialog1.FilterIndex = 2;
openFileDialog1.RestoreDirectory = true;
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
try
{
FileName = openFileDialog1.FileName;
string text = System.IO.File.ReadAllText(FileName);
datfile = text.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None);
//Added on 2015-12-02
maxRec = datfile.Length - 1;
PageCount = maxRec / pageSize;
LoadPage(MyFOrmat);
}
catch (Exception ex)
{
MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message);
}
}
}
LOADPAGE Code:
public void LoadPage(string Format, bool isFindAndReplace = false)
{
int startRec;
int endRec;
if (currentPage == PageCount)
{
endRec = maxRec;
}
else
{
endRec = pageSize * currentPage;
}
dataGridView1.Rows.Clear();
if (recNo == 0)
{
dataGridView1.Columns.Clear();
}
int rowindex = 0;
startRec = recNo;
for (int RowCount = startRec; RowCount <= endRec; RowCount++)
{
if (datfile[RowCount].ToString() != "" )
{
if (RowCount == 0)
{
string[] column = datfile[RowCount].Split('þ');
for (int i = 0; i < column.Length - 1; i++)
{
if (column[i].ToString() != "" && column[i].ToString() != "\u0014")
{
DataGridViewTextBoxColumn dgvtxtcountry = new DataGridViewTextBoxColumn();
dgvtxtcountry.HeaderText = column[i].ToString();
dgvtxtcountry.Name = column[i].ToString();
dataGridView1.Columns.Add(dgvtxtcountry);
cmbList.Add(column[i]);
i += 1;
}
}
}
if (RowCount != 0)
{
dataGridView1.Rows.Add();
string[] column = datfile[RowCount].Split('þ');
int index = 0;
for (int i = 1; i < column.Length - 1; i++)
{
if (column[i].ToString() != "\u0014")
{
if (i == 3)
{
dataGridView1.Rows[rowindex].Cells[index].Value = Convert.ToDateTime(column[i]).ToString(Format);
}
else
{ dataGridView1.Rows[rowindex].Cells[index].Value = column[i].Trim('þ'); }
index += 1;
i += 1;
}
}
rowindex += 1;
}
}
recNo += 1;
}
}
FIND and REPLACE Event:
private void btnFindandReplace_Click(object sender, EventArgs e)
{
Form2 f = new Form2();
f.cmbColumnCombo.DataSource = cmbList;
f.ShowDialog();
for (int i = 0; i <= dataGridView1.Rows.Count - 1; i++)
{
//dataGridView1.Rows[rowindex].Cells[index].Value = Convert.ToDateTime(column[i]).ToString(Format);
if (dataGridView1.Rows[i].Cells[f.cmbColumnCombo.Text].Value.ToString().ToLower().Contains(f.txtfind.Text.ToLower()))
{
//dataGridView1.Rows[i].Cells[f.cmbColumnCombo.Text].Value = dataGridView1.Rows[i].Cells[f.cmbColumnCombo.Text].Value.ToString().ToLower().Replace(f.txtfind.Text.ToLower(), f.txtreplace.Text);
//bulidDataRow(i);
if (!string.IsNullOrEmpty(f.txtfind.Text))
{
dataGridView1.Rows[i].Cells[f.cmbColumnCombo.Text].Value = dataGridView1.Rows[i].Cells[f.cmbColumnCombo.Text].Value.ToString().Replace(f.txtfind.Text, f.txtreplace.Text);
#region Commented
//dataGridView1.Rows[i].Cells[f.cmbColumnCombo.Text].Value = dataGridView1.Rows[i].Cells[f.cmbColumnCombo.Text].Value.ToString().Replace(f.txtfind.Text, f.txtreplace.Text);
//bulidDataRow(i);
#endregion
}
}
}
}
private void btnNext_Click(object sender, EventArgs e)
{
currentPage += 1;
if (currentPage > PageCount)
{
currentPage = PageCount;
//Check if you are already at the last page.
if (recNo == maxRec)
{
MessageBox.Show("You are at the Last Page!");
return;
}
}
LoadPage(MyFOrmat);
}
Please let me know if anything needs to be added.
To summarize your requirements:
You want to read largish data files of 10k - 500k records
You want to display them in chunks/pages in a DataGridView
You want allow the user to modify the data:
The user can merge columns
The user can use change&replace on the data
Date&time columns may be split
Possibly modified data shall be saved
The way I see it you have two approaches:
Either cache the data
Or cache the actions
Caching the actions is doable but clearly a lot more fuss, both in coding the caching and in keeping the data synchronized.
So caching the data would be my first choice.
Here is a sketch of how to break up the functionality:
A function to read in the whole data and load them into a DataTable
Functions for the initial display and for displaying a certain page
Functions for doing each of the changes on the list of rows.
After calling a changing function the current page display must be refreshed.
Keeping the total quantity of data in memory shouldn't really be a problem today; I notice that you are reading in all data as strings already in the datFile array. Reading it into a table will spare you to split it over and over..
A DataTable.DataRow also offers nice properies like HasErrors or RowState. And its Items can have a dedicated type to help with formatting..
Note however that DataRow doesn't have a (real) constructor; instead it must be created from a DataTable, so you will first have to create one from your columns!
The display code would use a pageSize and a currentFirstLine variable; it can clear and add the rows into the DGV or you could go for a binding solution with the DataTable you need anyway holding the DataRows and a filter on the table or rather on an BindingSource.
Of course you can also use a structure of your own, maybe a simple as a string[] or a List<string>to hold the row data..
If you are interested in the idea of caching the actions, you could create a ChangeAction class that holds:
the type
the parameters needed, ie, the column(s), the change&replace strings etc..
Then in a List<ChangeAction> you would store them as they happen and then apply them to each unchanged row. But here comes the first catch: You will need to know which row have been changed and maybe if a ChangeAction can be applied twice without screwing up the data.. More problems may or may not come later, depending on the details of you data and actions..
Here is an example of how to set up the binding using class level variables:
DataTable DT = new DataTable();
BindingSource BS = new BindingSource();
int pageSize = 0;
int firstLineVisible = 0;
After filling the table you can bind it and set the initial filer:
BS.DataSource = DT;
dataGridView1.DataSource = BS;
pageSize = (dataGridView1.ClientSize.Height - dataGridView1.ColumnHeadersHeight)
/ dataGridView1.Rows[0].Height;
int l1 = firstLineVisible; int l2 = firstLineVisible + pageSize;
BS.Filter = "Nr >= " + l1 + " and Nr < " + l2;
When scrolling you simply change the firstLineVisible and rest the Filter and the DataSource..
Now all your data modifications should work on the data in the DataTable using the SetField method!
Also note that you need one column in your data that holds a running number. If your data don't have one it is easy to include it by adding it to the data lines:
The column gets autogenerated in the DataGridView. For the DataTable we want to have it in the first data line; I use a separator string sep:
var lines = File.ReadAllLines(fileName).ToList();
..
string[] sep = { ";" };
var p0 = ("Nr" + sep[0] + lines[0]).Split(sep, StringSplitOptions.None );
DT.Columns.Clear();
for (int i = 0; i < p0.Length; i++) DT.Columns.Add(p0[i], typeof(string));
Adding it to the data is just as simple:
for (int l = 1; l < lines.Count; l++)
{
var p = (l + sep[0] + lines[l]).Split(sep, StringSplitOptions.None);
DT.Rows.Add(p);
}
You can hide the number column if you want to..:
dataGridView1.Columns["Nr"].Visible = false;
You should add that line right after setting the Filter.
I have DataGridView in that one combobox the combobox values are loaded from one table after selecting combobox value i want to update other columns with respective data but this is working only for one row i want update all row.. please give any suggestion for code change.
private void dataGridView2_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
if (dataGridView2.IsCurrentCellDirty)
{
for (int i = 0; i < (dataGridView2.Rows.Count)-1; i++)
{
try
{
if (dataGridView2.Rows[i].Cells[1].Value.ToString() != "")
{
ConnectionDB gridRdata = new ConnectionDB("SELECT * FROM Ready_Made_Master WHERE RM_Name='" + dataGridView2.Rows[i].Cells[1].Value.ToString() + "';");
DataTable redydata = gridRdata.returntable();
dataGridView2.Rows[i].Cells[2].Value = redydata.Rows[i][2].ToString();
}
}
catch
{
}
}
}
}
After the for loop,try rebinding the gridview ie
for (int i = 0; i < (dataGridView2.Rows.Count)-1; i++)
{
}
ConnectionDB gridRdata = new ConnectionDB("SELECT * FROM Ready_Made_Master");
DataTable redydata = gridRdata.returntable();
gridRdata .Datasource=redydata ;
gridRdata .Databind();
Please make the necessary chnges in Select Statement.
I have been saving into the ComboBox a value out of the selected column in datagridview with below code.
My question is:How can I prevent duplicate records when I save the values into the ComboBox? How can I do that?
Code:
int ColumnIndex = dgUretimListesi.CurrentCell.ColumnIndex;
CmbAra.Text = "";
for (int i = 0; i < dgUretimListesi.Rows.Count; i++)
{
CmbAra.Items.Add(dgUretimListesi.Rows.Cells[ColumnIndex].Value.ToString());
}
Please try this
private void dgvServerList_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
try
{
if (e.ColumnIndex == 1)
{
string id = dgvServerList[e.ColumnIndex, e.RowIndex].Value.ToString();
int duplicaterow = 0;
for (int row = 0; row < dgvServerList.Rows.Count; row++)
{
if (row != e.RowIndex && id == dgvServerList[e.ColumnIndex, row].Value.ToString())
{
duplicaterow = row + 1;
MessageBox.Show("Duplicate found in the row: " + duplicaterow);
this.dgvServerList[e.ColumnIndex, e.RowIndex].Value = "";
break;
}
}
}
}
catch
{
}
}
you could first transfer your datagridview items to a dictionary (which guarantees uniqueness) and then transfer that dictionary content to the combobox. or you could check for uniqueness yourself using a 'Contains' method on the combobox. you could even tie the dictionary to the combobox as a source for the combobox items.
Dictionary<string,bool> d = new Dictionary<string,bool>();
int ColumnIndex = dgUretimListesi.CurrentCell.ColumnIndex;
CmbAra.Text = "";
for (int i = 0; i < dgUretimListesi.Rows.Count; i++)
{
d[dgUretimListesi.Rows.Cells[ColumnIndex].Value.ToString()] = true;
}
CmbAra.Items.AddRange(d.Keys);
Use a set:
int ColumnIndex = dgUretimListesi.CurrentCell.ColumnIndex;
CmbAra.Text = "";
HashSet<string> set = new HashSet<string>();
for (int i = 0; i < dgUretimListesi.Rows.Count; i++)
{
string s = dgUretimListesi.Rows.Cells[ColumnIndex].Value.ToString();
if(!set.Contains(s)) {
CmbAra.Items.Add(s);
set.Add(s);
}
}
by using the following check and then determine to add or not
if(CmbAra.Items.Contains(dgUretimListesi.Rows.Cells[ColumnIndex].Value.ToString()))
You can use the following code part.
if(!(CmbAra.Items.Contains(dgUretimListesi.Rows.Cells[ColumnIndex].Value.ToString())))
{
CmbAra.Items.Add(dgUretimListesi.Rows.Cells[ColumnIndex].Value.ToString());
}
else
{
MessageBox.Show("Value Already exists , not added");
}
I am binding the data in a data table from two different datagrid
protected ICollection BindGenerateReport()
{
DataTable dtGenerateReport = new DataTable();
DataRow drRow;
for (int innerCounter = 0; innerCounter < dgInvoices.Columns.Count; innerCounter++)
{
dtGenerateReport.Columns.Add();
}
for (int counter = 0; counter < dgInvoices.Items.Count+dgReceipts.Items.Count;counter++ )
{
drRow = dtGenerateReport.NewRow();
if (dgReceipts.Columns[6] == dgInvoices.Columns[1])
{
for (int innerCounter = 0; innerCounter < dgReceipts.Columns.Count; innerCounter++)
{
drRow[innerCounter] = dgReceipts.Columns[innerCounter];
}
}
else
{
for (int innerCounter = 0; innerCounter < dgInvoices.Columns.Count; innerCounter++)
{
drRow[innerCounter] = dgInvoices.Columns[innerCounter];
}
}
dtGenerateReport.Rows.Add(drRow);
}
DataView dv = new DataView(dtGenerateReport);
return dv;
}
and i am binind the function a event click like that
protected void btnGenerateReport_Click(object sender, EventArgs e)
{
dgGenerateReport.DataSource = BindGenerateReport();
dgGenerateReport.DataBind();
}
but i want to know that what exactlu datagrid.columns[number] returns (the value inside that column or the datatype or only the column collection ).My code is not working
The columns collection will return an instance of a type derived from DataGridColumn, this could be a BoundColumn, ButtonColumn etc.
Check the MSDN Article for more information.