Table1 Fig.
Name | Marks
Pritam | 80
Aruna | 85
Uttaran | 90
Total | 255
DataTable dtStudentInfo = table1;
dataGridView1.DataSource = dtStudentInfo;
After Clicking on the column header name datagridview sort in ascending order of students' name. But I want the Total row always stays at the last of list.
I want to know if there is any way by which I can remove the last row from the list which will be sorted. If this is not possible then suggest any way by which i can get the result. NOTE: I don't want any external button to sort the list.
I've solved the problem by the following way:
DataGridViewRow dgRowTotalCount;
private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
{
if (e.RowIndex == -1)
{
dgRowTotalCount = (DataGridViewRow)dataGridView1.Rows[((DataGridView)sender).Rows.Count - 1].Clone();
for (Int32 index = 0; index < ((DataGridView)sender).Rows[((DataGridView)sender).Rows.Count - 1].Cells.Count; index++)
{
dgRowTotalCount.Cells[index].Value = ((DataGridView)sender).Rows[((DataGridView)sender).Rows.Count - 1].Cells[index].Value;
}
((DataGridView)sender).Rows.RemoveAt(((DataGridView)sender).Rows.Count - 1);
}
}
private void dataGridView1_Sorted(object sender, EventArgs e)
{
DataTable dtDGVCopy = new DataTable();
foreach (DataGridViewColumn col in dataGridView1.Columns)
{
dtDGVCopy.Columns.Add(col.Name);
}
foreach (DataGridViewRow row in dataGridView1.Rows)
{
DataRow dRow = dtDGVCopy.NewRow();
foreach (DataGridViewCell cell in row.Cells)
{
dRow[cell.ColumnIndex] = cell.Value;
}
dtDGVCopy.Rows.Add(dRow);
}
dtDGVCopy.Rows.Add();
for (Int32 i = 0; i < dgRowTotalCount.Cells.Count - 1; i++)
{
dtDGVCopy.Rows[dtDGVCopy.Rows.Count-1][i] = dgRowTotalCount.Cells[i].Value;
}
dataGridView1.DataSource = null;
dataGridView1.DataSource = dtDGVCopy;
}
But its not smooth as it was before. If there is any way by which i can make it's performance as it was before that would be great.
I know this is an old question, but here is a solution I've come up with. Use the SortCompare event on the grid to override the sorting for a specific row:
private void dgvData_SortCompare(object sender, DataGridViewSortCompareEventArgs e)
{
if (dgvData.Rows[e.RowIndex1].Cells[0].Value.ToString() == "Total" ||
dgvData.Rows[e.RowIndex2].Cells[0].Value.ToString() == "Total")
{
if (dgvData.SortOrder == SortOrder.Ascending)
{
e.SortResult = -1;
}
else
{
e.SortResult = 1;
}
e.Handled = true;
}
}
Now any row that has "Total" in the first column will always sort to the end of the grid.
(If you allow columns to be reordered then you'll need to figure out how to check the correct column)
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'm trying the folowing:
List<object>selectedRows = new List<object>();
foreach (DataGridViewRow row in dataGridView1.SelectedRows)
{
selectedRows.Add(row);
}
for (int i = 0; i < selectedRows.Count; i++)
{
selectedRowsList.Items.Add(selectedRows[i]);
}
I have a button and GridView. Now I want the user to select rows manually and store them in a List, so that I can put them into a Listbox (the values with "" or ";" side by side). So take the row from GridView and display it as a row in my Listbox. Multiple rows should be one below the other like it's displayed in the GridView). How to do that? The code i've posted stores the values as "{index = ...}".
foreach (DataGridViewRow row in dataGridView1.SelectedRows)
{
listBox1.Items.Add(row.Cells[0].Value.ToString() +" "+row.Cells[1].Value.ToString() +" "+ row.Cells[2].Value.ToString());
}
When we select rows using RowHeader, we get result as below
This happens because Microsoft's ListBox displays the value of the DataGridViewRow object's ToString() method. Therefore you can fill the ListBox with string objects that are representation of every row in the DataGridView. So in the button's click event I modified your code as follows:
private void button1_Click(object sender, EventArgs e)
{
List<string> selectedRows = new List<string>();
foreach (DataGridViewRow row in dataGridView1.SelectedRows)
{
string currentRow = string.Empty;
foreach (DataGridViewCell cell in row.Cells)
{
currentRow += String.Format("{0} ", cell.FormattedValue);
}
selectedRows.Add(currentRow);
}
for (int i = 0; i < selectedRows.Count; i++)
{
this.listBox1.Items.Add(selectedRows[i]);
}
}
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 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);
}