Row index provided is out of range. Parameter name: index - c#

I trying to move selected items from one gridview to another gridview, when the user has selected items(more than one item). It reads the first row and third row item in gridview and sends it to gridview2.
Gives me the above error in try catch. How do I read each row by row without jumping to read to the third row when user has selected a second row. I have been working on this for a week now. I am a beginner in C#. Thanks in advance.
// dgSubjectGridView2 is cleared, first Gridview(dgSubjectGridView) is moving selected item from its grid to dgSubjectGridView2
private void btnGo_Click(object sender, EventArgs e)
{
dgSubjectGridView2.Rows.Clear();
try
{
DataGridViewRow row = new DataGridViewRow();
//Counts the total number of rows in dgSubjectGridView
for (int i = 0; i < dgSubjectGridView.Rows.Count; i++)
{
row = dgSubjectGridView.Rows[i];
Boolean checkstate;
checkstate = Convert.ToBoolean(row.Cells[0].Value);
foreach (DataGridViewRow item in dgSubjectGridView.Rows)
{
if (checkstate == true)
{
dgSubjectGridView2.Rows.Add(false, item.Cells[1].Value.ToString());
dgSubjectGridView.Rows.RemoveAt(row.Index);
}
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
//End
}
}

It seems that you are twice looping through the same GridView row collection. Replace your try block with the following code and see if it produce the desired result.
try
{
foreach (DataGridViewRow row in dgSubjectGridView.Rows)
{
Boolean checkstate = Convert.ToBoolean(row.Cells[0].Value);
if (checkstate == true)
{
dgSubjectGridView2.Rows.Add(false, row.Cells[1].Value.ToString());
dgSubjectGridView.Rows.RemoveAt(row.Index);
}
}
}

Related

C# DataGridView reset row new file

I open a CSV File in my DataGridView. When i click on button "Down" the next row is selected.
Problem: when I open a new CSV and click "Down", automatically the selection jumps to the row number of the last selected number of the old CSV.
Example: I select row 11 and open a new file. Row 1 is selected until I press "Down". Instead of row 2, row 11 is selected.
private void btn_down_Click(object sender, EventArgs e)
{
if (dataGridView1.Rows.Count != 0)
{
selectedRow++;
if (selectedRow > dataGridView1.RowCount - 1)
{
selectedRow = 0;
port.Write("...");
}
dataGridView1.Rows[selectedRow].Selected = true;
dataGridView1.FirstDisplayedScrollingRowIndex = dataGridView1.SelectedRows[0].Index;
}
}
You should not use an internal counter to store the selected row since the selection could be changed by other components (in your case by changing the data source). Just make use of the dataGridView1.SelectedRows to get the currently selected row. Based on this row select the next one. Here is a simple implementation:
private void btn_down_Click(object sender, EventArgs e)
{
//Make sure only one row is selected
if (dataGridView1.SelectedRows.Count == 1)
{
//Get the index of the currently selected row
int selectedIndex = dataGridView1.Rows.IndexOf(dataGridView1.SelectedRows[0]);
//Increase the index and select the next row if available
selectedIndex++;
if (selectedIndex < dataGridView1.Rows.Count)
{
dataGridView1.SelectedRows[0].Selected = false;
dataGridView1.Rows[selectedIndex].Selected = true;
}
}
}

Equivalent WinForm DataGridView code to WPF DataGrid

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!

Put selected rows from a GridView to a Listbox

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]);
}
}

DataGridViewRow index out of range exception on refresh

I have a data grid view in my C# application. When I highlight the line and I hit delete, the row will delete but when I run the update and refresh command I am getting an index out of range exception
private void btnDeleteMember_Click(object sender, EventArgs e)
{
foreach (DataGridViewRow item in this.dgvAllFaculty.SelectedRows)
{
int row = item.Index;
FacultyMember member = memberList[row];
if (row >= 0)
{
memberList.RemoveAt(row);
Save();
this.dgvAllFaculty.Update();
this.dgvAllFaculty.Refresh();
return;
}
}
}
While debugging I notice it fails on the refresh call.The error I get is
System.IndexOutOfRangException: Index 1 does not have a value
at System.Windows.Forms.CurrencyManager.get_Item(Int32 index)
at
System.Windows.Forms.DataGridView.DataGridViewDataConnection.GetError(Int32 rowIndex)
If there something else you need to see let me know. I am wondering if when the refresh is happening its mad cause it still thinks the second row is there?
Ok, I changed my code around a little bit and its now working. I had to reload the data from the json file first before refreshing.
private void btnDeleteMember_Click(object sender, EventArgs e)
{
int count = this.dgvAllFaculty.SelectedRows.Count;
foreach (DataGridViewRow item in this.dgvAllFaculty.SelectedRows)
{
int i = item.Index;
FacultyMember member = memberList[i];
memberList.RemoveAt(i);
Save();
}
if (count > 1)
{
MessageBox.Show(String.Format("{0} faculty memebers deleted", count));
}
else
{
MessageBox.Show("Faculty Member Deleted");
}
// Load the newest data from file before refreshing the view
ViewAll_Load(sender, e);
this.Refresh();
}

Using CellDirtyStateChanged event with CheckBoxColumns

I have the following code that I am using in order to get the total count of employees selected within a datagridview.
I want it to calculate as soon as a user checks a check box or when a user unchecks it.
private void dgvEmployeesToProcess_CellDirtyStateChanged(object sender, EventArgs e)
{
try
{
if (dgvEmployeesToProcess.CurrentCell.ColumnIndex == 4)
{
txtNoOfEmpToProcess.Text = string.Empty;
int count = 0;
foreach (DataGridViewRow row in dgvEmployeesToProcess.Rows)
{
DataGridViewCheckBoxCell checkBox = (DataGridViewCheckBoxCell)row.Cells[4];
if (Convert.ToBoolean(checkBox.Value) == true)
{
count = count + 1;
}
}
// show total count in textbox
txtNoOfEmpToProcess.Text = count.ToString();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
The problem that I am having is that when I check the checkbox in row[0], ie. the first, checkBox.Value is always null and count = 0. When I click on a second checkbox, count = 1 and so forth.
What do I need to do in order to get the count correct? Do I need to use something other than CellDirtyStateChanged?
Add this line at the start of dgvEmployeesToProcess_CellDirtyStateChanged:
dgvEmployeesToProcess.CommitEdit(DataGridViewDataErrorContexts.Commit);
This will commit the changes (in example check/uncheck a particular column) so you will get the actual result.

Categories

Resources