I am trying to populate a DataGridView based on the selected item in a ComboBox, I have this part working.
However, I need to be able to clear the grid before adding the new data from a new item rather than it just adding on to the end.
How do I clear a DataGridView before adding items to it?
Firstly, null the data source:
this.dataGridView.DataSource = null;
Then clear the rows:
this.dataGridView.Rows.Clear();
Then set the data source to the new list:
this.dataGridView.DataSource = this.GetNewValues();
If it's bound to a datasource -
dataGridView.DataSource=null;
dataGridView.Rows.Clear();
Worked for me.
You can clear DataGridView in this manner
dataGridView1.Rows.Clear();
dataGridView1.Refresh();
If it is databound then try this
dataGridView1.Rows.Clear() // If dgv is bound to datatable
dataGridView1.DataBind();
IF you want to clear not only Data, but also ComboBoxes, Checkboxes, try
dataGridView.Columns.Clear();
DataGrid.DataSource = null;
DataGrid.DataBind();
You can assign the datasource as null of your data grid and then rebind it.
dg.DataSource = null;
dg.DataBind();
You could take this next instruction and would do the work with lack of perfomance. If you want to see the effect of that, put one of the 2 next instructions (Technically similars) where you need to clear the DataGridView into a try{} catch(...){} finally block and wait what occurs.
while (dataGridView1.Rows.Count > 1)
{
dataGridView1.Rows.RemoveAt(0);
}
foreach (object _Cols in dataGridView1.Columns)
{
dataGridView1.Columns.RemoveAt(0);
}
You improve this task but its not enough, there is a problem to reset a DataGridView, because of the colums that remains in the DataGridView object. Finally I suggest, the best way i've implemented in my home practice is to handle this gridView as a file with rows, columns: a record collection based on the match between rows and columns. If you can improve, then take your own choice a) or b): foreach or while.
//(a): With foreach
foreach (object _Cols in dataGridView1.Columns)
{
dataGridView1.Columns.RemoveAt(0);
}
foreach(object _row in dataGridView1.Rows){
dataGridView1.Rows.RemoveAt(0);
}
//(b): With foreach
while (dataGridView1.Rows.Count > 1)
{
dataGridView1.Rows.RemoveAt(0);
}
while (dataGridView1.Columns.Count > 0)
{
dataGridView1.Columns.RemoveAt(0);
}
Well, as a recomendation Never in your life delete the columns first, the order is before the rows after the cols, because logically the columns where created first and then the rows.It would be a penalty in terms of correct analisys.
foreach (object _Cols in dataGridView1.Columns)
{
dataGridView1.Columns.RemoveAt(0);
}
foreach (object _row in dataGridView1.Rows)
{
dataGridView1.Rows.RemoveAt(0);
}
while (dataGridView1.Rows.Count > 1)
{
dataGridView1.Rows.RemoveAt(0);
}
while (dataGridView1.Columns.Count > 0)
{
dataGridView1.Columns.RemoveAt(0);
}
Then, Put it inside a function or method.
private void ClearDataGridViewLoopWhile()
{
while (dataGridView1.Rows.Count > 1)
{
dataGridView1.Rows.RemoveAt(0);
}
while (dataGridView1.Columns.Count > 0)
{
dataGridView1.Columns.RemoveAt(0);
}
}
private void ClearDataGridViewForEach()
{
foreach (object _Cols in dataGridView1.Columns)
{
dataGridView1.Columns.RemoveAt(0);
}
foreach (object _row in dataGridView1.Rows)
{
dataGridView1.Rows.RemoveAt(0);
}
}
Finally, call your new function ClearDataGridViewLoopWhile(); or ClearDataGridViewForEach(); where you need to use it, but its recomended when you are making queries and changing over severall tables that will load with diferents header names in the grieView. But if you want preserve headers here there is a solution given.
dataGridView1.Rows.Clear();
dataGridView1.Refresh();
If you want to clear all the headers as well as the data, for example if you are switching between 2 totally different databases with different fields, therefore different columns and column headers, I found the following to work. Otherwise when you switch you have the columns/ fields from both databases showing in the grid.
dataTable.Dispose();//get rid of existing datatable
dataTable = new DataTable();//create new datatable
datagrid.DataSource = dataTable;//clears out the datagrid with empty datatable
//datagrid.Refresh(); This does not seem to be neccesary
dataadapter.Fill(dataTable); //assumming you set the adapter with new data
datagrid.DataSource = dataTable;
private void ClearGrid()
{
if(this.InvokeRequired) this.Invoke(new Action(this.ClearGrid));
this.dataGridView.DataSource = null;
this.dataGridView.Rows.Clear();
this.dataGridView.Refresh();
}
refresh the datagridview and refresh the datatable
dataGridView1.Refresh();
datatable.Clear();
datatable.Clear();
dataGridView1.DataSource = datatable;
For having a Datagrid you must have a method which is formatting your Datagrid. If you want clear the Datagrid you just recall the method.
Here is my method:
public string[] dgv_Headers = new string[] { "Id","Hotel", "Lunch", "Dinner", "Excursions", "Guide", "Bus" }; // This defined at Public partial class
private void SetDgvHeader()
{
dgv.Rows.Clear();
dgv.ColumnCount = 7;
dgv.RowHeadersVisible = false;
int Nbr = int.Parse(daysBox.Text); // in my method it's the textbox where i keep the number of rows I have to use
dgv.Rows.Add(Nbr);
for(int i =0; i<Nbr;++i)
dgv.Rows[i].Height = 20;
for (int i = 0; i < dgv_Headers.Length; ++i)
{
if(i==0)
dgv.Columns[i].Visible = false; // I need an invisible cells if you don't need you can skip it
else
dgv.Columns[i].Width = 78;
dgv.Columns[i].HeaderText = dgv_Headers[i];
}
dgv.Height = (Nbr* dgv.Rows[0].Height) + 35;
dgv.AllowUserToAddRows = false;
}
dgv is the name of DataGridView
The solution is:
dataGridView1.Rows.RemoveAt(0);
Clears the grid and preserves the columns.
YourGrid.Items.Clear();
YourGrid.Items.Refresh();
This is working to me
'int numRows = dgbDatos.Rows.Count;
for (int i = 0; i < numRows; i++)
{
try
{
int max = dgbDatos.Rows.Count - 1;
dgbDatos.Rows.Remove(dgbDatos.Rows[max]);
btnAgregar.Enabled = true;
}
catch (Exception exe)
{
MessageBox.Show("No se puede eliminar " + exe, "",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}`
Solution is:
while (dataGridView1.RowCount > 1)
{
dataGridView1.Rows.RemoveAt(0);
}
You could take this next instruction and would do the work with lack of perfomance. If you want to see the effect of that, put one of the next instruction where you need to clear the DataGridView into a try{} catch(...){} finally block and wait what occurs.
while (dataGridView1.Rows.Count > 1)
{
dataGridView1.Rows.RemoveAt(0);
}
while (dataGridView1.Columns.Count > 0)
{
dataGridView1.Columns.RemoveAt(0);
}
Related
I have a data in DataGrid with n Rows, and the DataGrid is ReadOnly. Now my goal is to when I select any row or rows and then press EDIT Button then all the selected rows only becomes ReadOnly = false. so that I want to edit some data in selected row(s). After this when I press the update button then only the selected rows are updated using EntityFramework.
I done this task in WinForm DataGridView. Now I want the same thing in WPF DataGrid.
private void editCust_Click(object sender, EventArgs e)
{
if (dataGridView1.SelectedRows.Count > 0)
{
foreach (DataGridViewRow item in dataGridView1.SelectedRows)
{
for (int i = 1; i <= 3; i++)
{
item.Cells[i].ReadOnly = false;
}
}
}
else
{
MessageBox.Show("No Row Is Selected To Edit.");
}
}
private void updateCust_Click(object sender, EventArgs e)
{
if (dataGridView1.SelectedRows.Count > 0)
{
foreach (DataGridViewRow item in dataGridView1.SelectedRows)
{
cutable.Customer_Name = (string)item.Cells[1].Value;
cutable.Counter = int.Parse(Convert.ToString(item.Cells[2].Value));
cutable.Buying_Cost = float.Parse(Convert.ToString(item.Cells[3].Value));
for (int i = 1; i <= 3; i++)
{
item.Cells[i].ReadOnly = true;
}
}
db.SaveChanges();
MessageBox.Show("Record Is Update.");
}
else
{
MessageBox.Show("No Row Is Selected To Update.");
}
}
First convert DataGridView to DataTable then to DataGrid
For DataGridView to DataTable
Use this:
DataTable myDataTable=(DataTable)(myDataGridView.DataSource);
For more reference go through DataGridView to DataTable
Now for DataTable to DataGrid
Use this:
myDataGrid.ItemsSource=myDataTable.DefaultView;
myDataGrid.AutoGenerateColumns = true;
myDataGrid.CanUserAddRows = false;
For more reference go through DataTable to DataGrid
Comment for any query
UPDATE:
Try to create to your own code and logic, do not depend on direct solutions given by someone.
Well a similar issue I found in StackOverflow[Solved].
Refer to this question how to edit select row in datagrid in wpf
Hope it helps!
I have a method that stores each line in a gridview into the database, then if the save is successful, removes the row; but if it isn't successful (cannot be stored in the db) it does not remove the row. Unfortunately, I can't get the row-removal to work properly.
This is my current code:
public static void SavePAC(PlantAreaCode_CreateView CView)
{
List<int> removeRows = new List<int>();
// For each cell in the DataGrid, stores the information in a string.
for (rows = 0; rows < CView.dataGridView1.Rows.Count; rows++)
{
correctSave = false;
if (CView.dataGridView1.Rows[rows].Cells[col].Value != null)
{
// Creates a model, then populates each field from the cells in the table.
PModel = new PlantAreaCode_Model();
PModel.AreaCode = Convert.ToString(CView.dataGridView1.Rows[rows].Cells[0].Value);
PModel.AreaName = Convert.ToString(CView.dataGridView1.Rows[rows].Cells[1].Value);
PModel.Comments = Convert.ToString(CView.dataGridView1.Rows[rows].Cells[2].Value);
// Passes the model into the Database.
Database_Facade.Operation_Switch(OPWRITE);
}
if (correctSave == true) // correctSave is set in the database insert method.
{
removeRows.Add(rows);
}
}
foreach (int i in removeRows)
{
CView.dataGridView1.Rows.RemoveAt(0); // Deletes all bar the last row, including any rows that cause errors
}
}
I have also tried:
foreach (int i in removeRows)
{
CView.dataGridView1.Rows.RemoveAt(i);
}
But that crashes at halfway, because the Rows index keeps changing each time a row is removed.
How can I achieve this? How can I remove a row if the save is successful, but keep it if there is an error?
May this help:
1] Make sure correctSave is being modified correctly.
2] Revert the loop flow, Looping backward allow to remove the row processed by the loop without affecting the index of the next row to process.
for (rows = CView.dgvCreate.Rows.Count - 1; rows >= 0 ; rows--)
3] Use CView.dataGridView1.Rows.RemoveAt(rows);
Try to populate collection of rows for removing with DataGridViewRow not with index. This works for me.
public void SavePAC(PlantAreaCode_CreateView CView)
{
List<DataGridViewRow> removeRows = new List<DataGridViewRow>();
foreach (DataGridViewRow row in CView.dataGridView1.Rows)
{
correctSave = false;
if (row.Cells[col].Value != null)
{
// Creates a model, then populates each field from the cells in the table.
PModel = new PlantAreaCode_Model();
PModel.AreaCode = Convert.ToString(row.Cells[0].Value);
PModel.AreaName = Convert.ToString(row.Cells[1].Value);
PModel.Comments = Convert.ToString(row.Cells[2].Value);
// Passes the model into the Database.
Database_Facade.Operation_Switch(OPWRITE);
}
if (correctSave == true) // correctSave is set in the database insert method.
{
removeRows.Add(row);
}
}
foreach (DataGridViewRow rowToRemove in removeRows)
{
CView.dataGridView1.Rows.Remove(rowToRemove);
}
}
You have to sort removeRows in descending order.
List<int> removeRowsDesc = removeRows.OrderByDescending(i => i);
Then use the foreach loop
foreach (int i in removeRowsDesc)
{
CView.dataGridView1.Rows.RemoveAt(i);
}
This way the reindexing wont affect the deletion.
I have a WPF DataGrid theDataGrid bound to a DataSet ds containing a table. I want to enable the user to remove lines by first selecting them in the grid and then pressing a button (positioned somwhere outside of the datagrid). I finally arrived at the following lines of code which do what I want, but which I consider rather ugly:
DataSet ds = new DataSet();
...
// fill ds somehow
...
private void ButtonClickHandler(object Sender, RoutedEventArgs e)
{
List<DataRow> theRows = new List<DataRow>();
for (int i = 0; i < theDataGrid.SelectedItems.Count; ++i)
{
// o is only introduced to be able to inspect it during debugging
Object o = theDataGrid.SelectedItems[i];
if (o != CollectionView.NewItemPlaceholder)
{
DataRowView r = (DataRowView)o;
theRows.Add(r.Row);
}
}
foreach(DataRow r in theRows)
{
int k = ds.Tables["producer"].Rows.IndexOf(r);
// don't remove() but delete() cause of update later on
ds.Tables[0].Rows[k].Delete();
}
}
Is there a better way to do this? E.g. one which needs only one loop and without having to check for the NewItemPlaceHolder explicitly, or possible a more efficient way to access the rows which are to be deleted?
(I already figured out that I must not remove anything from the ds in the first loop, since then theDataGrid.SelectedItems.Count changes everytime the loop is executed...)
In order to remove row selected on button click you can try:
private void ButtonClickHandler(object sender, RoutedEventArgs e)//Remove row selected
{
DataRowView dataRow = (DataRowView)dataGridCodes.SelectedItem; //dataRow holds the selection
dataRow.Delete();
}
I think it works by just one loop:
int count=theDataGrid.SelectedItems.Count;
int removedCount=0;
while (removedCount < count)
{
try{
Object o = theDataGrid.SelectedItems[0];
}
catch{ break;}
if (o == CollectionView.NewItemPlaceholder)
continue;
DataRowView r = (DataRowView)o;
r.Row.Delete();
removedCount++;
}
You can remove the double loop by iterating backwards :
private void ButtonClickHandler(object Sender, RoutedEventArgs e) {
for (int i = theDataGrid.SelectedItems.Count-1; i>=0; --i)
if (theDataGrid.SelectedItems[i] != CollectionView.NewItemPlaceholder)
ds.Tables[0].Rows[i].Delete();
}
I have a CheckedListBox and I would like to check all the items that are in another List.
This code does not work since the CheckedItems property is read-only and the types do not match, but it gives the best idea of what I want to do.
checkedListBox1.DataSource = DataSetSelectAll().Tables[0];
checkedListBox1.ValueMember = "id_table";
checkedListBox1.DisplayMember = "name";
List<tableClass> list = MyCheckedList();
checkedListBox1.CheckedItems = list;
I know this is wrong but do not know how to explain it better.
Its not possible to set(check) many items at a time like this, checkedListBox1.CheckedItems = list;
better you can use for loop like:
List<tableClass> list = MyCheckedList();
for (int count = 0; count < checkedListBox1.Items.Count; count++)
{
if (list.Contains(checkedListBox1.Items[count].ToString()))
{
checkedListBox1.SetItemChecked(count, true);
}
}
andy's answer is right but I have an easier solution. My solution works in windows application.
DataTable dt = MyCheckedList();
foreach (DataRow dr in dt.Rows)
{
for (int i = 0; i < checkedListBox1.Items.Count; i++)
{
if (dr["valueMember"].ToString() == ((DataRowView)checkedListBox1.Items[i])[0].ToString())
{
checkedListBox1.SetItemChecked(i, true);
}
}
}
Note: dt must fill with a dataTable which has all checkedList Values.
I'm not sure why, but I SetItemChecked(index, tf) wasn't giving me what I wanted. This is how I solved it - explicitly setting the CheckedState.
for (int i = 0; i < myCheckedListBox.Items.Count; i++)
{
if (boolList[i])
{
myCheckedListBox.SetItemCheckState(i, CheckState.Checked);
} else
{
myCheckedListBox.SetItemCheckState(i, CheckState.Unchecked);
}
}
I have a datagridview with one DataGridViewCheckBoxColumn and some other TextBox Columns. I want to loop through each cell and see if the checkbox is checked then do something. I am using the following looping method. Is there a better way to do??
I have used or condition because in some computers it brings .Value as Checked and in some it bring .Value as true.
foreach (DataGridViewRow row in dataGridView.Rows)
{
if ((bool)(row.Cells["Checkbox"]).Value || (CheckState)row.Cells["Checkbox"].Value == CheckState.Checked)
{
// Do something
}
}
Thanks in advance.
i think this will be faster than foreach
for (int i = 0; i < dataGridView.Rows.Count -1; i++)
{
DataGridViewRow row = dataGridView.Rows[i];
if ((bool)(row.Cells["Checkbox"]).Value
|| (CheckState)row.Cells["Checkbox"].Value == CheckState.Checked)
{
// Do something
}
}
It worked for me using following code:
foreach (DataGridViewRow row in dgv_labelprint.Rows)
{
if (value.Value == null)
{
}
else
if ((Boolean)((DataGridViewCheckBoxCell)row.Cells["CheckBox"]).FormattedValue)
{
//Come inside if the checkbox is checked
//Do something if checked
}
}
Have a look at this link DirtyCellChanged You can then keep track of which rows have been checked and do your work, rather than having to loop through the whole table.
This event is useful when dealing with checkboxes as users sometimes click check, and then don't commit the edit by clicking somewhere else.
It's worked good for me in the past.
int subId;
List<int> olist= new List<int>();
for (int i = 0; i < gvStudAttend.Rows.Count; i++)
{
bool Ischecked = Convert.ToBoolean(gvStudAttend.Rows[i].Cells["Attendance"].Value);
if (Ischecked == true)
{
subId = gvStudAttend.Rows[i].Cells["SubjectID"].Value.ToString();
olist.Add(subId );
}
}