0
votes

I have a little issue using a datagridview.

I have an empty DataGridView and I would like to manually add rows to it that I also need to be able to move.

So in order to accomplish that I have a bound an empty list as the datasource of the DataGridView.

I also have an Add Row button that creates a new item of a specific class in that list. Once I have added the new item to the list, I refresh the datasource of the DatagridView.

So far everything is working. My issue arises when I try to edit one of the fields in the datagridview. As soon as I click on one of the cells, I receive an error message stating:

Index -1 does not have a value

The error is not coming from any of my code, it's coming from the editor. The stack trace I get is this:

StackTrace:
       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.OnCellMouseDown(HitTestInfo hti, Boolean isShiftDown, Boolean isControlDown)
       at System.Windows.Forms.DataGridView.OnCellMouseDown(DataGridViewCellMouseEventArgs e)
       at System.Windows.Forms.DataGridView.OnMouseDown(MouseEventArgs e)
       at System.Windows.Forms.Control.WmMouseDown(Message& m, MouseButtons button, Int32 clicks)
       at System.Windows.Forms.Control.WndProc(Message& m)
       at System.Windows.Forms.DataGridView.WndProc(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
       at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
       at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
       at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.Run(Form mainForm)
       at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()

Does anybody have an idea why this is happening? It almost seems like the DataGridView doesn't know that there is a row there, eventhough an item in my list has been created and it's showing in the DataGridView.

By the way. Once I restart the application, I can click on it without any problem, no errors popping up. So it´s only when I have just linked an empty list to the datasource of the DataGridView and I have added the first row to the datasource.

For your reference this is the view when I have clicked the Add Row button.  Next when I click on the Description-field, the application crashes. The error-message

I hope anybody has an idea about this.

Thanks, Kenneth

1
If you bind an empty list and have your own button for adding a new row, how can there be any cells showing to click on? Do you have code in one of the cell click events? Also, I refresh the datasource of the DatagridView is suspicious - Ňɏssa Pøngjǣrdenlarp
the button adds a new item to the list. Next I set the datasource of the DataGridView to null and next I re-associate the list to the datasource. - Cainnech
Appearantly this question stackoverflow.com/q/8832587/4425684 is about the same thing but there they suggest to use a bindinglist, but that would cause an issue for me as I need to use that list also for other stuff which would mean I would have to convert the list. - Cainnech
There is an easier way to do all that. AllowUserToAddRows provides a new row. When they click on it, there are several events you can respond to in order to add a new row (NewRowNeeded). Now, you dont need to "refresh" the DataSource because the DGV is fully aware of the changes. - Ňɏssa Pøngjǣrdenlarp

1 Answers

0
votes

List does not implement IBindingList so the grid does not know about your new items.

Bind your DataGridView to a BindingList<T> instead.

You can use a BindingList as it offers all the functionality of a List along with the binding functionality so simply use a binding list instead. This is possible because it implements both the IList and IBinding interfaces. Ive shown an example below:

public partial class Form1 : Form
{

    private BindingList<Person> people = new BindingList<Person>();

    public Form1()
    {
        InitializeComponent();

        dataGridView1.DataSource = people;
    }

    private void button1_Click(object sender, EventArgs e)
    {
        people.Add(new Person("John"));
        people.ResetBindings();
    }
}