Programatically adding rows in DataGridview is failing

Programatically adding rows in DataGridview is failing

Old forum URL: forums.lhotka.net/forums/t/7636.aspx


Vinodonly posted on Wednesday, September 16, 2009

I want to programatically add rows in DataGridview but it is failing..

Main thing is that code should be written in a generic way i.e. it shud work for all CSLA Objects..

I'm trying following :-

((BindingSource)dgv.DataSource).AddNew()

Or

If i try to get the BO directly from Datasource of DGV and try to cast it to IBindingList and then call AddNew

In both cases, ExtendedBindingList's Insert Item is throwing following exception :-

Operation is not valid due to current state of object.

Vinodonly replied on Thursday, September 17, 2009

can anybody help for this..

JonnyBee replied on Thursday, September 17, 2009

Hi,

Which version of Csla are you using?

Add the following code to your Csla.BusinessListBase.cs (using this myself on Csla 3.6.3):

    protected override object AddNewCore()
    {
        var item = DataPortal.CreateChild<C>();
        Add(item);
        return item;
    }

    public new void Add(C item)
    {
        item.SetParent(this);
        Core.UndoableBase.ResetChildEditLevel(item, this.EditLevel, false);
        item.EditLevelAdded = _editLevel;
        base.Add(item);
        InsertIntoMap(item, IndexOf(item));
    }


This code will allow the generic BusinessListBase to add "empty" child objects (calling DataPortal_Create or ObjectFactoryClass.Create with no parameters).

You can use the BindingSourceNavigator control in WindowsForms or call BindingSource.AddNew method.

Note: your BindingSource must have AllowNew set to True.

/jonnybee

Vinodonly replied on Thursday, September 17, 2009

I’m having the same version like yours.. and other all code is also there i.e. addnewcore is added and allownew is true and I’m tried both methods i.e. through bindingsource and directly through list..

FYI.. the normal down arrow adding record is working, it is only in programaticlaly it is failing..

Except the other method which you have given is not there.. I’m need this functionality for multiple copy paste of rows in which I hv to add rows..



Is The other code must for this to work ? If that is the case then I will have to change all my bo’s..

ajj3085 replied on Thursday, September 17, 2009

Something else must be going on. I add rows using AddNew all the time using unit tests, and its always worked for me.

If you set VS to break on the exception you're getting, can you see whre the exception is being thrown?

Vinodonly replied on Thursday, September 17, 2009

kindly note error is thrown in ExtendedBindingList's InsertItem and follwing exception is thrown :-

Operation is not valid due to current state of object.

ajj3085 replied on Thursday, September 17, 2009

Well, this is the EBL InsertItem in its entirety:

protected override void InsertItem(int index, T item)
{
base.InsertItem(index, item);
OnAddEventHooks(item);
}

So either the BindingList is throwing the exception, or something is going on in OnAddEventHooks. Either way, you should be able to debug to see whats going on.

Vinodonly replied on Saturday, September 19, 2009

I was able to find more details on the problem but i was still not able to solve it..

Programatically row adding is done when user copies multiple rows and tries to paste it..

If I do the paste on the last row (i.e. the one which is already existing) then new rows are inserted without any problem.

The problem comes when i press down arrow first and insert a new row and then try to do paste..

I think somehow it is related with that the row which was added manually is not properly committed and that is what is creating this error..

but i'm not able to solve it..

any ideas..

Tom_W replied on Saturday, September 19, 2009

Ah, OK, that's quite an important extra bit of info.

My guess is that by clicking into the new row both the grid and the bindingsource are in an 'edit' mode of some description - I'm not sure exactly how that works, but if you have added a row then you have caused AddNewCore to fire and a new object for that row to be created but not to be committed or cancelled so it's reasonable to think there could be a problem here as the grid/bindingsource doesn't know what to do with that record. 

It's also possible that the newly created row is invalid if there is any data the user must complete, so it would then become impossible to commit that record.  But... I'm guessing you don't want that record committed anyway, as the user has only moved to a new row for the purposes of choosing where to paste the existing data, rather than because they want to manually enter new data in that new row (i.e. they don't really want a new row at all).

Therefore, I think the solution is to cancel the creation of the new row in your paste code before you then add the new rows that are to be pasted.  Effectively you want to programatically do the same as the user hitting the Esc key on the row before hitting paste. 

Programatically that should be achievable via the ICancelAddNew interface that BLB implements.  Just prior to pasting try casting your list to ICancelAddNew and then calling icanListObject.CancelNew.  That should get rid of the rogue extra record before you then add (paste) the new ones.

This looks like useful code that may help:  DGV on MSDN social

Vinodonly replied on Saturday, September 19, 2009

Brilliant !! Thanks a lot for your help..

Actually I'm already getting a reference for BindingSource and calling CancelEdit before the paste operation is working..Paste is now working without any errors..

Is it ok ? or I should get a BO Ref only and call CancelNew on that..

Tom_W replied on Saturday, September 19, 2009

Glad it's working Big Smile [:D]

Actually your approach is probably better, databinding can be really fussy and it is really easy to get edit level mismatches by changing the underlying BOs directly when those same BOs are also bound to UI elements. 

In truth I'm never 100% confident that I know why these edit level mismatches occur, but I have definitely found it safer to go via the bindingsource for bound BOs rather than the changing the underlying objects directly - What I would say though is if you have a solution that works, then that's the right solution to stick with!

Copyright (c) Marimer LLC