10
votes

I have some trouble with setting the last row in my datagridview selected. I select the last row this way:

if (grid.Rows.Count > 0)
{
    try
    {
        grid.Rows[grid.Rows.Count - 1].Selected = true;
        grid.CurrentCell = grid.Rows[grid.Rows.Count - 1].Cells[1]
    }
    catch (IndexOutOfRangeException)
    { }
    catch (ArgumentOutOfRangeException)
    { }
}

When I execute this code I get an exception: IndexOutOfRangeException occurred: Index-1 does not have a value.

When I debug the Rowscollection and the corresponding Cells collection I see both collections are filled. The index also exists of the Rows and Cells collection.

I have no clue what I am doing wrong here. Someone who can help me out here? Thnx

EDIT:

Here is the complete exception:

System.IndexOutOfRangeException: Index -1 does not have a value.
at System.Windows.Forms.CurrencyManager.get_Item(Int32 index)
at System.Windows.Forms.CurrencyManager.get_Current()
at System.Windows.Forms.DataGridView.DataGridViewDataConnection.OnRowEnter(DataGridViewCellEventArgs e)
at System.Windows.Forms.DataGridView.OnRowEnter(DataGridViewCell& dataGridViewCell, Int32 columnIndex, Int32 rowIndex, Boolean canCreateNewRow, Boolean validationFailureOccurred)
at System.Windows.Forms.DataGridView.SetCurrentCellAddressCore(Int32 columnIndex, Int32 rowIndex, Boolean setAnchorCellAddress, Boolean validateCurrentCell, Boolean throughMouseClick)
at System.Windows.Forms.DataGridView.set_CurrentCell(DataGridViewCell value)
8
Code seems fine. Have you tried debugging it? On what line of code are you getting the error? - Aseem Gautam
Try a Quick Watch for grid.Rows[grid.Rows.Count - 1].Cells[1] and see what it returns. - KMån
@Aseem: the line is: grid.CurrentCell = grid.Rows[grid.Rows.Count - 1].Cells[1] - Martijn
@KMan: Then I get the IndexOutOfRangeException. When I do grid.Rows[grid.Rows.Count - 1].Cells.Count I get 5 - Martijn

8 Answers

17
votes

Try:

dataGridView1.ClearSelection();//If you want

int nRowIndex = dataGridView1.Rows.Count - 1;
int nColumnIndex = 3;

dataGridView1.Rows[nRowIndex].Selected = true;
dataGridView1.Rows[nRowIndex].Cells[nColumnIndex].Selected = true;

//In case if you want to scroll down as well.
dataGridView1.FirstDisplayedScrollingRowIndex = nRowIndex;

Gives following output: (Last row, scrolled and selected)

alt text

4
votes

I know this may be a little late but it may be of use to someone else.

Have you tried this :

grid.Rows.Row[grid.Rows.Count -1].Selected = true;

In my windows app I first used your code in my datagridview and I got the same exception.. and then it came to me at night when I was in my bed (I'm a newbie to programming).

If I write as : Rows[Rows.count-1] the first row is "0" and "0-1 = -1" so its out of range :)

Then when I changed my code to Rows.Row[index] it worked! :)


An alternative if you use c# 3.0 and higher: check out CellAddress(); ;)

Sincerely

3
votes

Have you thought about using Linq for this?

    grid.Rows.OfType<DataGridViewRow>().Last().Selected = true;
    grid.CurrentCell = grid.Rows.OfType<DataGridViewRow>().Last().Cells.OfType<DataGridViewCell>().First(); // if first wanted
1
votes

Your 'catch' block for IndexOutOfRangeException is empty, and will not display any error at all.

Either your question is not exact, or the exception is being thrown somewhere else.

EDIT: Having looked through your call stack that you added, I can see that the error is, indeed, not being thrown here, but rather in the CurrencyManager class's Current/Item properties, which is ultimately being triggered by the call to the CurrentCell setter.

Bottom line: the problem is not in this code; the exception is being thrown by some other piece of code triggered by your setting the current cell.

1
votes
dataGridView1.Rows[dataGridView1.Rows.Count - 1].Selected = true;
0
votes

Eventually the last row is empty because it's the empty row with which the user can add a new row. This row cannot be selected. Have you tried grid.Rows.Count - 2? As an alternative, you can set AllowUserToAddRows to false.

0
votes

To avoid the IndexOutOfRangeException make sure only to select a visible row. I suggest:

// Find last visible row
DataGridViewRow row = dataGridView1.Rows.Cast<DataGridViewRow>().Where(r => r.Visible).Last(); 
// scroll to last row if necessary
dataGridView1.FirstDisplayedScrollingRowIndex = dataGridView1.Rows.IndexOf(row);
// select row
row.Selected = true;
0
votes

It's very easy. use: dataGridView.CurrentCell=dataGridView[ColumnIndex, RowIndex];
dataGridView[X,y]...
instead of
dataGridView[Y, X]...