Data Binding - DataGridView and Detail Controls - Changes Not Reflected

Data Binding - DataGridView and Detail Controls - Changes Not Reflected

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


xxxJasonxxx posted on Thursday, September 13, 2007

Hi guys,

Thanks for taking the time to read my post.

I'm having a strange issue with business objects bound to Windows controls and some changes not being reflected.  I'm hoping one of you guys has seen this before and can offer some suggestions.

I am using CSLA version 2.1.4.0.  I’ve created a Purchase Order object (editable root), which contains a Payments collection (editable child list), which holds Payments objects (editable child).

I set up each of these objects as a "Data Source" in Visual Studio 2005, so I could drag and drop the objects or their properties onto a Windows form as bound controls.

At the top of my Windows form, I dragged the Payments collection onto the form as a DataGridView.  I set the DataGridView to readonly because I do not want the users making changes directly inside the grid.  The grid displays only minimal payment information necessary to help the user identify which payment he/she is looking for.

At the bottom of the form I dragged various properties from the Payments object, like "Amount" or "Payment Type", onto the form as textboxes, listboxes, etc.  These controls show all detailed information about one payment.

My intentions for this layout are that the user will select a payment in the DataGridView at the top of the form and then at the bottom of the form the user will view or edit all the details of the selected payment using the various textboxes, listboxes, etc.

At the bottom of the form, I also placed an "Add" button for adding new payments (to the Payments collection and DataGridView) and a “Remove” button for removing them.

At first it appeared that everything worked as I expected.  For example, I would make a change to the "Amount" textbox at the bottom of the screen and once I tabbed away from the textbox, the "Amount" value would also change inside the DataGridView at the top of the form.

Then I noticed something really weird after I clicked the “Add” button a few times.  I can add one payment and everything works fine.  But if I add two or more payments, things break – data changes made inside the controls at the bottom of the form are no longer reflected in the DataGridView at the top of the form.  The weirdest thing is that everything still works perfectly for any original payments that were in the DataGridView when the form was first loaded and still works perfectly for the first new payment that I added.  But for the second new payment and all new payments after that, changes to the detail controls at the bottom of the form are not reflected in the DataGridView at the top of the form.  Doh! 

Using the debugger I was able to confirm that my Payment object’s properties (like “Amount”) are always being changed correctly, regardless of whether the DataGridView reflects the changes or not.

Here’s the relevant code from my “New” constructor where my Order object is passed in as a parameter:
   Me.PaymentsBindingSource.DataSource = mobjOrder.Payments

Here’s the relevant code from my “Add” button’s click handler:
   mobjOrder.Payments.AddNew(mobjOrder)

There’s not a lot of code other than that – most of the functionality is being done automatically by Windows data-binding and the CSLA framework.

Does anybody have any suggestions about what is happening and how I can resolve this?

Thanks,

Jason

xal replied on Thursday, September 13, 2007

This usually has to do with the GetIdValue() override not returning a unique value. Any chance that's the case?
It usually is with int IDs and them defaulting to "0".

Andrés

jhw replied on Thursday, September 13, 2007

I've seen that problem as well. Like Andres said, it is about a non unique value. If the database already uses an int as a key, then I add a guid for identifying things locally while working with them. That has solved this problem for me.

 

Heath

xxxJasonxxx replied on Thursday, September 13, 2007

I think you're right.  I checked my Payment object - a new payment does not have an Id value until after the it saved for the first time (it gets the Id from the database insert).  So the "GetIdValue" method is returning an empty string until the payment is saved once.  I'm going to try assigning a temporary unique Id when a new payment is created so the "GetIdValue" method works correctly prior to saving and then change the Id to the real value after the save.  I'll post again later and confirm whether that worked.  I bet you've found the problem though.  Thanks for the help!

Jason

RockfordLhotka replied on Thursday, September 13, 2007

I'm actually considering making GetIdValue() virtual, but not abstract, and providing a default implementation using Guid values. This would be in the base classes. That would avoid these issues in the default case, and would still allow you to do an override when desired.

xxxJasonxxx replied on Thursday, September 13, 2007

Just wanted to confirm - that did fix the problem.  Thanks again!

Jason

xal replied on Thursday, September 13, 2007

Rocky,
Do you think it's really worth it? It means adding yet another field to the base class that could be pottentially big (if you're aiming at guids). Sometimes we move a lot of data through remoting and that could be a big perf hit. I know: overriding it would keep it null so it might not be such a big problem, but thenagain, you're opening the door for people to ignore that they need to override it and that could create perf problems and usage problems that would very difficult to track to GetIdValue().

Am I being too dramatic? Perhaps it's not such a big deal, but I'm sceptic when it comes to changing something that creates an issue from time to time to something else that could create new/undiscovered issues.


Andrés

RockfordLhotka replied on Thursday, September 13, 2007

This is why I bring it up – soliciting feedback.

 

It does seem to be a recurring pain point for many people though.

 

Rocky

 

From: xal [mailto:cslanet@lhotka.net]
Sent: Thursday, September 13, 2007 4:36 PM
To: rocky@lhotka.net
Subject: Re: [CSLA .NET] Data Binding - DataGridView and Detail Controls - Changes Not Reflected

 

Rocky,
Do you think it's really worth it? It means adding yet another field to the base class that could be pottentially big (if you're aiming at guids). Sometimes we move a lot of data through remoting and that could be a big perf hit. I know: overriding it would keep it null so it might not be such a big problem, but thenagain, you're opening the door for people to ignore that they need to override it and that could create perf problems and usage problems that would very difficult to track to GetIdValue().

Am I being too dramatic? Perhaps it's not such a big deal, but I'm sceptic when it comes to changing something that creates an issue from time to time to something else that could create new/undiscovered issues.


Andrés

xxxJasonxxx replied on Monday, September 17, 2007

I think these unique Id issues are a significant concern that probably warrants exploration.

 

I suspect that many people probably run into trouble with this......especially people like me who are forced to get their unique ids from a legacy app’s database and therefore don't have an real Id until after their object is saved for the first time.

 

I peeked inside the CSLA framework code, but could not come up with a good generic way of dealing with this unique Id issue from inside the framework that would cover all scenarios.  Hopefully, one of you more experienced guys will eventually come up with a good solution.

 

I ended up generating and setting a temporary unique Id (global variable) while in "DataPortal_Create()".  Then in "GetIdValue()", I check "IsNew()" to determine whether to return the value of the temporary id variable or the real id variable.  I don't know if this is the best or most elegant solution, but so far it looks like this is going to work for me.  If anyone has a better idea, please post it.

 

For what it’s worth, my current opinion is that these unique Id issues will probably have to be resolved by training rather than by tweaking the framework.  The CSLA framework is pretty awesome and makes our life so much easier, but a framework can only do so much.  At some point it’s up to all of us programmers to take the time to read the entire book, read this forum, and learn how to use the CSLA framework correctly.

 

Rocky….thanks so much for the framework, books, forums (especially your frequent participation)…..you’re awesome!

 

Jason

JugerHiTech replied on Wednesday, March 24, 2010

Hi Jason,

  Can you send me the solution for this issue....Very Thank You~~

I ended up generating and setting a temporary unique Id (global variable) while in "DataPortal_Create()".  Then in "GetIdValue()", I check "IsNew()" to determine whether to return the value of the temporary id variable or the real id variable. 

Thank you for your kindly help

Edwin

ajj3085 replied on Wednesday, March 24, 2010

That should be the solution... although if you're using a newer version of Csla, there's no need to override GetIdValue at all anymore.

JugerHiTech replied on Wednesday, March 24, 2010

Hi Andy,

  Thank you for your answer.

am using CSLA version 3.8.2.  But I still got this issue...

My app got one window, which has one tab control on that.

On the tab control, I got 2 tab: 

one tab is datagridview (that datasource is a bindingsource which is come from businesslistbase)(7 columns)

another tab is detailview(7 columns map to the columns in the datagridview)

Now when I load all data from db, the datagridview and detailview work very well (ex, move row, add row, change column value)

but after I save all the modified rows(New, Update rows) for the first time, something happened....

When I modify the detailview column (ex, StorerTypeID), and click the gridview tab, the (StorerTypeID) column in the gridview

didn't change its value... and when I click the (StorerTypeID) column in the gridview, then it refresh the new value!

Also, when I change the (StorerTypeID) column in the gridview, then click the detailview tab,

the (StorerTypeID) column in the detailview didn't change its value, even when I click that column, it still cann't change

to the new value which I just maintain in the gridview....

Could you give me some advise or some example for that ?  Very Thanks.

 

Edwin

 

Copyright (c) Marimer LLC