views:

729

answers:

2

I have a datagridview which we will call dataGridViewExample.

My object (the uncommon datatypes is because my database is SQLite):

class MyObject
{
    public Int64 Vnr { get; set; }
    public string Name { get; set; }
    public Single Price { get; set; }
    public int Amount { get; set; }
}

Here is the relevant code:

//This form gets called with a .ShowDialog(); in my form1.

private List<MyObjecte> ExampleList = new List<MyObject>();

public MyForm()
{
    dataGridViewExample.DataSource = OrdreInkøbsListe;
}


private void AddtoDataGridViewExample()
{
    //Add a new MyObject to the list
    ExampleList.Add(new myObject()
                 {
                     Vnr = newVnr,
                     Amount = newAmount,
                     Price = newPrice,
                     Name = newName
                 });

    //refresh datasource
    dataGridViewExample.DataSource = null;
    dataGridViewExample.Refresh();
    dataGridViewExample.DataSource = OrdreInkøbsListe;
    ddataGridViewExample.Refresh();
}

When MyForm gets called with a .ShowDialog, it shows up fine and displays my DataGridView example just fine. As you can read from the code, the ExampleListis initially empty, so it just shows an empty datagridview with 4 columns: Vnr, Name, Price & Amount. If I click inside it etc. nothing happens - so everything is working as planned, so far.

Everytime I call AddtoDataGridViewExample() it adds the new object to the Datagridview, and the datagridview does update, listing all the objects added so far (they show themself as rows, again according to plan).

Now, remember that I just said that nothing happened if you clicked inside DataGridViewExample before I have called AddtoDataGridViewExample()? Well, after having called AddtoDataGridViewExample() once or more, the program will crash if I click inside DataGridViewExample (for example: the users wants to select a row). It throws an IndexOutOfRangeException and talks about an -1 index. It also throws the exception in the other form, on the line where I call MyForm with .ShowDialog();

I really am stuck on this, do you guys have any idea what is wrong?? My only clue is that I do believe the refresh of DataGridViewExample's datasource might be the cause of the problem. Another important note: I have yet bound any events to my DataGridViewExample. So you can rule that idea out.

Here is all DataGridViewExample's properties:

this.dataGridViewExample.AllowUserToAddRows = false;
this.dataGridViewExample.AllowUserToDeleteRows = false;
this.dataGridViewExample.AllowUserToResizeColumns = false;
this.dataGridViewExample.AllowUserToResizeRows = false;
this.dataGridViewExample.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.Fill;
this.dataGridViewExample.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.dataGridViewExample.Location = new System.Drawing.Point(591, 53);
this.dataGridViewExample.MultiSelect = false;
this.dataGridViewExample.Name = "dataGridViewExample";
this.dataGridViewExample.ReadOnly = true;
this.dataGridViewExample.RowHeadersVisible = false;
this.dataGridViewExample.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect;
this.dataGridViewExample.ShowEditingIcon = false;
this.dataGridViewExample.Size = new System.Drawing.Size(240, 150);
this.dataGridViewExample.TabIndex = 31;
+3  A: 

I guess the click event tries to get the currently selected row and do something with it, while dataGridViewExample.DataSource = null; clears the datasource, and the currently selected row becomes null.

If you set the DataGridView.DataSource to the list, you don't need to reset it to null, refresh, and reset it to the list again (and refresh again) to see the changes. It will be enough to just refresh the DataGridView.

You can also just try using an BindingList<T> object instead of a List<T>, which will automatically notify your grid of its internal changes (Adding and removing elements), and there's also an INotifyPropertyChanged interface you can implement on your MyObject class, that will make every property change in an object show on the grid (For any changes made to the object in the code, and not through the grid itself).

Noam Gal
This sounds extremely interesting. Could you show some code examples? Especially how to use the binding list and how I should call the refresh in my method
CasperT
I changed the list to bindinglist, removed all refresh code and added a single refresh. Everything seems to work perfectly, Thank you so much!! A quick request though: could you show a code example of how to remove a certain object from the bindinglist?
CasperT
Nevermind, figured it all out. Thanks again
CasperT
Glad to be of service.
Noam Gal
A: 

Have you tried running the debugger and break when InedxOutOfRangeException is thrown to see where the exception is thrown?

Select Debug > Exceptions then there's a Find button on the dialog so you don't have to browse through all of the possibilities.

ChrisF