views:

115

answers:

4

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)

+1  A: 

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.

Shaul
It does throw an excetpion in debug mode. The code stops running and VS is highlighting. But that is not the point. The point is, WHY is the exception thrown?
Martijn
I would use the "Immediate" window to confirm the value of grid.Rows.Count, then try accessing grid.Rows[0] or whatever number using an integer literal, just to make sure. I suspect the code here is not an exact copy of the code that's causing the exception, and somewhere in between that and what you *think* your code is doing lies the error.
Shaul
In the immediate window I have rows and cells in the collections
Martijn
Have modified my answer.
Shaul
EDIT: This DID NOT FIX MY PROBLEM! I still have the same Exception. I still have no idea what goes wrong. I only have these event handlers: `CellContentDoubleClick`and `CellDoubleClick`
Martijn
@Martijn - What did you find in the CurrencyManager form? The exception is originating there, in those methods I mentioned in my answer. Somewhere in the `Current` property you're making reference to the Item indexer property, with an index of -1, which obviously doesn't exist.
Shaul
To answer your question in the edit: I haven't create my own form in that namespace. I do use a control which is based on the windows datagrid (DevComponents' DotNetBar DataGridViewX). How can I check the CurrencyManager form?
Martijn
Ah, my mistake, apparently there *is* a CurrencyManager class in System.Windows.Forms (shoulda googled before opening my big mouth!) http://msdn.microsoft.com/en-us/library/system.windows.forms.currencymanager.aspx I've never seen it before or worked with it - but you clearly are, somewhere in your datagrid. That's about all I can tell you for now; hopefully I've pointed you more or less in the right direction. Good luck!
Shaul
So you think I have to look at the CurrencyManager from the Windows Form?
Martijn
A: 

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
danijels
No I have not. But I don't have the Extension methods `Last()` and `First()`. I have the using System.Linq
Martijn
sorry, I edited to correct linq now
danijels
Thanks. Tried your solution but I get the same Exception on this line: `grid.CurrentCell = grid.Rows.OfType<DataGridViewRow>().Last().Cells.OfType<DataGridViewCell>().Last();`
Martijn
it doesn't make sense to get IndexOutOfRangeException on code that does not use index property at all. Sure it's the same exception?
danijels
A: 

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.

Satanlike
I have tried your solution, but it didn't work.
Martijn
I already have that property set to false..
Martijn
-1 - that's called clutching at straws, not debugging.
Shaul
A: 

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

KMan
I've tried this, but it didn't work.
Martijn
@Martijn: I tested the code before posting. What exactly does not work?
KMan
On the line `dataGridView1.Rows[nRowIndex].Cells[nColumnIndex].Selected = true;` I get the annoying Exception
Martijn
@Martijn: Assuming the *exception* is same as in your question. Are you inserting any row manually? prior to binding?
KMan
@KMan: Before I select the last row I run this method: private void AddAppointmentsToGrid(IList<Appointment> appointments) { Collection<Appointment> apps = dgViewAfspraak.DataSource as Collection<Appointment>; dgViewAfspraak.DataSource = null; foreach (Appointment app in appointments) { apps.Add(app); } dgViewAfspraak.DataSource = apps; }(Don't know how to show code in comments)
Martijn
@Martijn: Can you restrict this method to add only one(or two) row(s) and test?
KMan
@KMan: take a look at my answer and the comments following - that might help point you folks in the right direction?
Shaul
@KMan: When I insert one record I have the same exception
Martijn
@Shaul: I don't know how to debug further on your suggestion
Martijn
I did some research on the CurrencyManager and I found that that has something to do with databinding on the Form. Shaul told me (well, actually the Exception) that the Current property is empty. In my method (shown above in the method) sets the DataSource to null. Now I've changed that code and I don't use DataSource = null anymore. Now the code is working correct without an Exception.
Martijn