WinForms dataBinding issue in 3.5.1 beta and a few questions.

WinForms dataBinding issue in 3.5.1 beta and a few questions.

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


tetranz posted on Friday, July 18, 2008

Hi Rocky and all

I'm finally making the effort to move to .NET 3.5 and CSLA 3.5. It looks great. Thanks for your efforts.

I'm having a problem with a simple EditableRootParent which has an EditableChildList which is bound to a form with a couple of text boxes for the root and a DataGridView for the children.

The list has AllowNew = true and AddNewCore() is overridden so that the grid can add items.

The problem occurs if I use a managed field for the childen list. As soon as I type in the last line of the grid, the new row is committed. I don't get the opportunity to cancel by pressing esc. It works fine if I change the children list to a traditional property with a private field variable.

I have a bare bones example (no db needed) to illustrate the problem if that would be useful. I had weirder things happening with my Janus grid so I thought I better try the DataGridView. Hopefully solving this problem will solve the Janus problems because that works nicely too with a traditional property / field.

Am I correct to assume that the advantage of using a managed field for the list property is that it then takes care of IsDirty and IsValid without me needing to override those?

I notice that the objects in ProjectTracker don't override GetIdValue(). Is that because it's using reference equality now so the id value is not used?

Ross

RockfordLhotka replied on Sunday, July 20, 2008

tetranz:

I have a bare bones example (no db needed) to illustrate the problem if that would be useful. I had weirder things happening with my Janus grid so I thought I better try the DataGridView. Hopefully solving this problem will solve the Janus problems because that works nicely too with a traditional property / field.


Ross, Please share the bare bones example, that should help find the problem. Others have reported similar things, but I don't have a simple, direct repro of the issue.

tetranz:

Am I correct to assume that the advantage of using a managed field for the list property is that it then takes care of IsDirty and IsValid without me needing to override those?

Yes, exactly. And all the parent-child event hookups for event cascading, and resetting the Parent reference on deserialization. All the hard-to-remember things you had to do to make parent-child really work are now automatic.

tetranz:

I notice that the objects in ProjectTracker don't override GetIdValue(). Is that because it's using reference equality now so the id value is not used?

That's right. Thanks to WPF rewriting the rules of equality (or at least severly restricting them), GetIdValue() is now totally optional - left in only for backward compat actually, but not really used in any meaningful way anymore.

tetranz replied on Monday, July 21, 2008

Ok, thanks Rocky. Attached is CSLATest.zip. You should be able to just update the reference to CSLA and build.

Click on the last row of the grid and the new item is immediately committed.

Comment and uncomment a couple of things in EditableRootParent to change the Children property it to a regular property and it all comes right. Click in the last row and the * is still there in the row header, type something in that new row and the pencil icon appears along with the next new row. Hit esc and we're correctly back to where we were.

Ross

RockfordLhotka replied on Monday, July 21, 2008

Wow!

 

(thanks for the simple repro – VERY useful)

 

I found the issue, and it amazes me that no one encountered this years ago.

 

People constantly implement event cascading – where a change in a child object (or list) results in a changed event at the parent level.

 

That turns out to be bad. Very bad. Having the parent raise a PropertyChanged event when its child list changes causes Windows Forms data binding to react badly. From what I can see, it causes the currency to “flicker” – change just long enough to force a commit of the current row in the grid.

 

So this is unfortunate. It means that BusinessBase can’t bubble a child list’s ListChanged event up as a PropertyChanged event. That was a very cool feature I added in 3.5 because a lot of people seem to do this on their own quite often (you can find many threads about that here on the forum). It is unfortunate that no one who’s done this on their own has encountered (or mentioned anyway) this really nasty side-effect…

 

I’m thinking that what I’ll do as an alternative, is have a virtual OnChildChanged() method in BusinessBase that gets called when a child’s ListChanged or PropertyChanged event comes in. That will allow notification to the parent that its child has changed. But I won’t continue to raise a PropertyChanged event because that’s obviously bad.

 

The other thing I could do is have BusinessBase declare a ChildChanged event that it can raise. That would also allow for the parent notification scenario, and would allow the UI to hook the event if it cared as well.

 

Opinions on which is better?

 

Rocky

tetranz replied on Monday, July 21, 2008

Thanks Rocky. I'm pleased you can see the problem. Microsoft must surely owe you something by now for the hours of frustation you must have spent messing with databinding and finding nearly every quick and "undocumented feature" in their code. Smile [:)]

RockfordLhotka:

I found the issue, and it amazes me that no one encountered this years ago.

 

I've always had problems, especially with grids, whenever I've tried bubbling up ListChanged events.

Here's a post from over two years talking about something similar.

 

http://forums.lhotka.net/forums/permalink/3821/3742/ShowThread.aspx#3742

RockfordLhotka:

I’m thinking that what I’ll do as an alternative, is have a virtual OnChildChanged() method in BusinessBase that gets called when a child’s ListChanged or PropertyChanged event comes in. That will allow notification to the parent that its child has changed. But I won’t continue to raise a PropertyChanged event because that’s obviously bad.

 

The other thing I could do is have BusinessBase declare a ChildChanged event that it can raise. That would also allow for the parent notification scenario, and would allow the UI to hook the event if it cared as well.

Opinions on which is better? 

I think I'd vote for the option 1 although I don't really have a strong preference. If you did option 2 then wouldn't you effectively do option 1 anyway as part of the standard event pattern?

ajj3085 replied on Monday, July 21, 2008

Hmm, I'll have to watch for this when I update Csla next.  I've bubbled events when one of my Csla BO's is actually a facade around other Csla BO's.  This made maintence easier, because each of the encapuslated BOs had distinct responsiblities, and made the UI easier, because there was only one object to which to bind.

I do have problem with grids sometimes though; the "new" row will drop down and there'll still be a "new" empty row.  Sometimes I have to highlight the empty gray row where new items are added and hit delete to get rid of it.. perhaps this behavior was caused by this bubbling?  I'm not sure I was bubbling anything in that case though either... could just be bad behavior on the part of Infragistics.

RockfordLhotka replied on Monday, July 21, 2008

I've decided on the ChildChanged event idea. That's more flexible overall, and supports the needs of both a parent object author and any UI author who cares that a child changed.

I've put the change into 3.5.1 in svn.

tetranz replied on Monday, July 21, 2008

I got the update. It's working nicely. Thanks.

Copyright (c) Marimer LLC