n-level undo and Windows Forms data binding

n-level undo and Windows Forms data binding

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


RockfordLhotka posted on Monday, May 08, 2006

There's been some discussion around some issues with n-level undo and data binding - specifically some nasty interactions between the BindingSource controls and the IEditableObject interface implemented by BusinessBase.

(this is the source of at least one thread in the old forum, and at least two email discussions I've been having with readers)

The primary symptom is that some object ends up with its edit level at 1 even though, by all understanding, all objects should have edit level of 0.

The most common scenario is where a parent object, with a collection of child objects, is bound to controls on a single form (detail controls for the parent, grid for the child collection). In this scenario, one of the child objects ends up at edit level 1, even though the parent and all other child objects edit levels are at 0 because of an ApplyEdit call.

After researching this, I think I have the answer. This is not due to a bug in CSLA, or even misbehavior by either data binding or CSLA. Rather it is a lack of complete understanding (at least on my part) as to how to properly use the BindingSource controls (or at least that's how I'm viewing this at the moment Wink [;)])

When you set up data binding in your form's constructor or load event handler, you may or may not manually call BeginEdit on the parent object (let's call it Employee). Then you set the BindingSource control's DataSource property:

Dim emp As Employee = Employee.GetEmployee(42)
emp.BeginEdit() ' optional
Me.EmployeeBindingSource.DataSource = emp

This not only starts data binding on the parent, but on its list of child objects (let's say phone numbers). Data binding, at this point, uses IEditableObject to call BeginEdit on the parent object - which is why the explicit BeginEdit call is optional - that call will happen one way or the other, but CSLA automatically makes sure only one call is actually honored.

Later, behind your Save button things get complex. In the book what I did (which is wrong) is to call ApplyEdit and Save. This, as it turns out, doesn't work right. Instead, you need to call EndEdit() on the BindingSource controls (not just the parent one, but the child one too!!) like this:

Me.EmployeeBindingSource.EndEdit()
Me.PhoneListBindingSource.EndEdit()

The first line automatically calls ApplyEdit (actually IEditableObject.EndEdit) on the parent object, which cases a cascade call down to all child objects. This puts all objects at edit level 0 EXCEPT for the one row in the grid that is currently being edited by the user.

The second line causes an ApplyEdit (actually IEditableObject.EndEdit) call to the currently selected child object in the child collection. The result is that its edit level is now also set to 0.

With that done, you can proceed to save your object - using or not using the Clone() technique as discussed in the book, etc.

I think this resolves the issues people have been having. Certainly it appears to resolve them in my testing around this problem. Once I have independant confirmation (which can come from any/all of you who care to test the solution) I'll put entries on www.lhotka.net as errata.

BARRY4679 replied on Monday, May 08, 2006

I am seeing what I assume to be another aspect of this problem, which doesn't involve the save button.
To use your example I have an employee with it's grid of phone numbers. I click on a grid row to open up a modal dialogue box for one of the phone numbers. I do a beginedit in the dialogue box because it would be confusing if a undo action inside the dialogue box was able to undo an uncommitted change which was made back in the mainform. The closing event of my dialogue box has a canceledit.

Use of the dialogue box elevates the editlevel of the examined phone number with relation to unexamined phone numbers (presumably due to the implicit beginedit mentined in your post, and Ross' (Tetranz4) post in the old newsgroup.

This means that a canceledit back in the mainform can cause corruption, as any rows examined by the dialogue box are not undone.

The issue can be resolved by calling canceledit twice on the phone number in the closing event of the dialogue box. Once for my BeginEdit and once for the implicit BeginEdit caused by the attachment of the datasource.

However, unless I have a bug of my own this observation seems to call into question whether, in this case, you are correct when you say "but CSLA automatically makes sure only one call is actually honored." ?

RockfordLhotka replied on Tuesday, May 09, 2006

CSLA automatically makes sure one call through IEditableObject is honored. It honors all explicit calls to BeginEdit, etc.

But I think your issue comes from the same source. The current row in the grid has its edit level elevated. Then you open your modal dialog, and so that child object's edit level isn't where it should be. I think that before opening the dialog you need to do an EndEdit on the BindingSource for the grid, thus lowering the edit level of the child object to match that of its parent and siblings.

This way the modal dialog can do its own BeginEdit, and Cancel/ApplyEdit (or use the BindingSource to do it).

BARRY4679 replied on Tuesday, May 09, 2006

Thanks, that works.

I was getting confused thinking that the EndEdit would commit the change, but of course it won't because the row is a child.

This is a tricky issue isn't it? We are having to explicitly back out the change to an invisible thing (editlevel) which was called by an implict call that we didn't make. This new .NET data binding support is helping productivity, but has it's traps for young players.

xal replied on Tuesday, May 09, 2006

Just a question (I haven't tested this thoroughly yet):
Does this also happen if your collection has allowedit = false and your grid is read only?
I'm not sure the collection's allowedit has anything to do here, because it's the child raising it's edit level, but if you have the grid as read only it shouldn't be raising the edit level. Right?

Andrés

RockfordLhotka replied on Tuesday, May 09, 2006

I haven't tested this with the grid and/or collection disallowing edit.

albator replied on Tuesday, May 09, 2006

Hi

I doesn't make the test with CSLA 2.0 but with the version 1.5 each time you move from one row to another in a readonly grid, BeginEdit is called causing serialization of the data bound business object.

The ApplyEdit /EndEdit/cancelEdit is never called because we don't make any modification operation on the row item.  The edit level is incremented by one each time you select another row.

This has big resource and performance impact.

In CSLA 1.5, I made a patch for temporally disable beginedit(serialization) for business object bound to a readonly grid.

Do you think the problem still existing in version 2.0?

Is there another way to avoid BeginEdit execution on readonly grid?

Thanks

Alain

 

 

 

 

 

razorkai replied on Tuesday, May 09, 2006

I was one of the people who had an issue with this, but have not had a chance to do any testing yet.  However, I will point out that I feel it is very confusing for a UI developer to have to call BeginEdit on the Object but then EndEdit on the BindingSource, especially when they have to do so for both the parent and child.  I get the feeling I will still have to leave the IEditableObject stuff out which is a shame as I do not want to change the Csla unless absolutely necessary.

John.

RockfordLhotka replied on Wednesday, May 10, 2006

1) There is no way I know of to prevent Windows Forms from calling BeginEdit. And if you defeat that call, then the user couldn't press ESC in a grid and have the cancel operation work. In other words, BeginEdit is actually required if you are doing in-place editing in a grid, or the user won't get the expected experience.

2) You do not have to manually call BeginEdit in .NET 2.0. I suggested doing that in the book, and it doesn't hurt anything - but in researching this issue it has become clear that the new BindingSource controls are very aggressive in calling BeginEdit (they do it immediately) and so there is no reason to call BeginEdit manually.

In .NET 1.x calling BeginEdit manually was wise because it avoided some edge case issues where edits could happen before BeginEdit was called automatically. But in .NET 2.0 this no longer appears to be the case and so I don't think calling it manually is important any more. Hopefully this addresses the UI developer confusion worry.

Norma_B replied on Thursday, June 29, 2006

I'm hesitant to resurrect an older thread, but I'm having a problem with a situation almost like the one described here.

I have a Products object (type BusinessListBase) which contains Product objects (BusinessBase). The Products object is bound to a Binding Source, which is used by a grid. Users can select a Product from the grid to display information in databound controls on the same form. That part is  working, as well as the code to save the Products back to the database.

Here's where it goes awry: The users can also select a Product and choose to edit it on another form. That form has a Binding Source, to which I pass the Product in question. They can use it to capture changes, and when closing the form have the choice to keep them (bsProduct.EndEdit) or discard them (bsProduct.CancelEdit). The first time the users open the form, capture changes, and save them, the changes are correctly saved. But second and subsequent times the form is used (and they are that indecisive, I've watched them do it), the changes do not make it, even though Product.IsDirty, IsValid (and therefore IsSavable, IIRC) are all True.

I've tried every fix proposed in this thread, to no avail. (but I've also put in almost 120 hours at work in the last 7 calendar days, so I'm not feeling very smart) Please tell me what I'm missing.

RockfordLhotka replied on Thursday, June 29, 2006

Do you call EndEdit on the first form's bindingsource, before passing the child object reference to the second form? And is that second form a modal dialog?

Norma_B replied on Friday, June 30, 2006

EndEdit yes, Modal no (I'll try that). If they want to continue editing the object on the main form, do I have to call any methods / reset any bindings?

RockfordLhotka replied on Friday, June 30, 2006

I don't know for sure - in that case you are entering territory I haven't researched. You just need to review Chapter 3 in terms of now n-level undo is implemented, and then be aware of how data binding will be invoking IEditableObject "on your behalf".
 
It seems quite possible that, with a non-modal window, both bindingsource objects will call BeginEdit on your object - elevating your edit level by 2. Yet navigating in the grid from one row to another will cause a call to ApplyEdit or CancelEdit, lowering it by 1 and possibly causing the loss of data in the non-model window.
 
Yeah, the more I think about this, the more I think it won't work. The problem is that you end up with dueling bindingsource objects. I wonder if Microsoft thought through this particular scenario when they created the bindingsource control...
 
Rocky


From: Norma_B [mailto:cslanet@lhotka.net]
Sent: Friday, June 30, 2006 9:25 AM
To: rocky@lhotka.net
Subject: Re: [CSLA .NET] n-level undo and Windows Forms data binding

EndEdit yes, Modal no (I'll try that). If they want to continue editing the object on the main form, do I have to call any methods / reset any bindings?

Norma_B replied on Friday, June 30, 2006

Thanks for your time, I'll make the detail forms modal and see how that works.

RockfordLhotka replied on Friday, June 30, 2006

One thing you can do for debugging is to expose a public CurrentEditLevel property in your objects:
 
Public ReadOnly Property CurrentEditLevel() As Integer
  Get
    Return EditLevel
  End Get
End Property
 
This way you could show the value in a label or column and thus monitor the current edit level of the object as it is used over time. You'd be able to see, on the form, what happens to the value.
 
You might need to override the CopyStateComplete and similar methods (see the UndoableBase discussion in Chapter 3) to call OnPropertyChanged for CurrentEditLevel so data binding knows when the value changes.
 
Rocky


From: Norma_B [mailto:cslanet@lhotka.net]
Sent: Friday, June 30, 2006 10:39 AM
To: rocky@lhotka.net
Subject: Re: [CSLA .NET] RE: n-level undo and Windows Forms data binding

Thanks for your time, I'll make the detail forms modal and see how that works.


tetranz replied on Friday, July 21, 2006

Hi Rocky and all

I'm resurrecting this thread and its related errata for page 491 of the C# book. I'm trying to build my own reference application a bit like ProjectTracker with everything "just right"

I think there is still an edit level problem when calling CancelEdit(). I can observe this with ProjectEdit.  The edit level of the child (ie ProjectResource) being edited does not go down when CancelEdit() is called on Project.

For debugging, I've exposed a public property EL on Project and ProjectResource which returns Editlevel. Then I have a button on ProjectEdit to show a message box.

Its kind of confusing clicking around with this but here's one set of steps that appears to go wrong somewhere.

The following three numbers are edit levels on:
_project, _project.Resources[0] and _project.Resources[1]

Open exiting project for edit
1,2,1 (Constructor called BeginEdit otherwise I guess it would be 0,1,0  before editing)

Edit a project field
1,2,1

Hit Cancel.
0,2,0

Edit a project field
1,3,1

Hit Cancel.
0,3,0

Edit a project field
1,4,1

etc ...

adding resourcesBindingSource.EndEdit() before _project.CancelEdit() seems to fix it. Does that seem a reasonable thing to do?  Also, I wonder if to be consistent with the constructor code we should probably have a _project.BeginEdit() after the CancelEdit(). I guess that doesn't make much difference.

Thanks
Ross

RockfordLhotka:

There's been some discussion around some issues with n-level undo and data binding - specifically some nasty interactions between the BindingSource controls and the IEditableObject interface implemented by BusinessBase.

(this is the source of at least one thread in the old forum, and at least two email discussions I've been having with readers)

The primary symptom is that some object ends up with its edit level at 1 even though, by all understanding, all objects should have edit level of 0.

[Snip ...]

RockfordLhotka replied on Sunday, July 23, 2006

I think the ultimate resolution here was that you shouldn't call CancelEdit on the object at all. Though that probably came up in a different thread.
 
But the end result of this was that you should only interact with the bindingsource object in terms of begin/cancel/end edit calls.
 
Rocky

tetranz replied on Monday, July 24, 2006

RockfordLhotka:
But the end result of this was that you should only interact with the bindingsource object in terms of begin/cancel/end edit calls.
Thanks Rocky, that seems to work. My cancel button now calls CancelEdit on the collection bindingSource and then CancelEdit on the root bindingSource.

A note of caution though. If you have ListChanged events from the collection bubbling up to the root and raising a PropertyChanged event (probably IsDirty), then you need to set RaiseListChangedEvents on the root bindingSource to false before calling the CancelEdits otherwise things get screwed up again. After the cancel you need to call ResetBindings() to catch up. That's the only way I've got it to work properly.

I'm finding that I really have to observe and test this EditLevel thing carefully. Its very easy to get it wrong.

Cheers
Ross

derfy replied on Sunday, July 30, 2006

Hi,

Having made some tests on ProjectTracker, i discovered that when CopyState method
gets called on a collection like projects, for example after a manual or a framework-call BeginEdit,  _bindingEdit is not set to true on the projectresources child objects as i would have been expected. I'm asking if is this the expected behaviour. If not so, is it correct overriding the  CopyStateComplete method on BusinessBase class end setting _bindingEdit to true, there?

I'm just a CSLA .NET newbie, so forgive me for the silly question, and for my english!

Thanks,

Nando

RockfordLhotka replied on Sunday, July 30, 2006

_bindingEdit should only be set to true in the case that BeginEdit was called through the IEditableObject interface.
 
CSLA .NET supports n-level undo. IEditableObject only supports 1 level undo. The _bindingEdit flag exists to allow IEditableObject to do its 1 level of undo by using the pre-existing n-level undo support in CSLA.
 
I discuss this quite a bit in Chapter 3 in the book, I recommend reading through that to get a better understanding of the design tradeoffs involved here.
 
Rocky


From: derfy [mailto:cslanet@lhotka.net]
Sent: Sunday, July 30, 2006 11:32 AM
To: rocky@lhotka.net
Subject: Re: [CSLA .NET] n-level undo and Windows Forms data binding

Hi,

Having made some tests on ProjecTracker, i discovered that when CopyState method
gets called on a collection like projects, for example after a manual or a framework-call BeginEdit,  _bindingEdit is not set to true on the projectresources child objects as i would have been expected. I'm asking if is this the expected behaviour. If not so, is it correct overriding the  CopyStateComplete method on BusinessBase class end setting _bindingEdit to true, there?

I'm just a CLSA newcomer, so forgive me for the silly question, and for my english!

Thanks.




derfy replied on Sunday, July 30, 2006

Hi Rocky,
What i missed before, was why the _bindingEdit member of the _project instance is set to true at the
 _project.BeginEdit() call in the ResourceEdit constructor, but not the _bindingEdit member of its
ProjectResources children objects. Your timely reply helped me to further clarify the role of the _bindingEdit member.

Thanks again for your patience.

Nando.

DanEssin replied on Sunday, July 30, 2006

Hi all from the other thread.

I too have put in over 120 hours chasing things related to binding and have to come to the following conclusion: It isn't worth the trouble. I'm going back to my old tried and true FillFormFromObject, and FillObjectFromForm methods. I call the first immediately after the object is populated by query or is new (which handles getting default values up on the form and all other fields cleared) and as the first action in my save button. After FillObjectFromForm has run, obj.IsDirty is true only if there were actually edits so puting the ApplyEdit and Save calls inside a test of obj.IsDirty avoids any unnecessary database calls.

It's simple, clean and trouble free AND it doesn't take 70 seconds to process the save like the bound version does, it only takes 500 miliseconds.

My conclusion: The CSLA Framework is great and MS data binding sucks. Any great thing can be dragged down by something really bad so I'm just going to side-step the bad and enjoy the framework.

Jimbo replied on Thursday, January 18, 2007

Mr DanEssen sounds like the project manager who cant graduate from 1999 technology. yes, FillFormFromObject, and FillObjectFromForm methods work fine in our vb6 apps, but that is just what we are attempting to replace with business objects and binding sources. One of the aspects that some poeple seem to misunderstand is that FillFormFromObject, and FillObjectFromForm methods, while reliable, put a totally different aspect on the overall application behaviour ( apart from OO) . The main aspect being that the business object (class) is not in control.

ajj3085 replied on Thursday, January 18, 2007

Databinding is reliable as well, as long as you use it correctly.  It sounds like the speed problems from DanEssen could easily be solved by turning of RaiseListChangedEvents to false while saving, then after the save turning it on again.

Jimbo replied on Thursday, January 18, 2007

Follow the master ajj

Jimbo replied on Thursday, March 22, 2007

This is an area that needs considerable help for most of my co-developers. It is fine to say that it is covered in the book; but this does not necessarily help in regard to concrete solutions. ( Project Tracker for example  in v1.1.2 avoids the implementation of undo) .
Let me set out a typical rather basic scenario:

We have a root collection business object.
This is bound to a DataGridView via a BindingSource.
In the UI (form) constructor, BeginEdit is set on the collection object. (standard stuff to initiate csla undo)
An item in the grid is edited and you tab off the row.
At this point the  grid binding has (presumably)_ Applied the edit.
You now click on Cancel (expecting to apply CancelEdit) but the edited row content remains undone.
You may also have edited many rows.. again expecting that all edits will be undone. As at no point did we manually or programatically call Begin, Apply or CancelEdit. Meaning, to most peoples that the edit level should still be at the point that we initiated in the constructor and that all action since would be undone.
But this is not the case ... Please explain how we deal with this and achieve the user experience that is expected.








Jimbo replied on Tuesday, March 27, 2007

Considering the number of tyre (tire) kickers on this thread, I would have expected more attention from the moderator.
The metrics indicate that this is a very important topic ( presumably because the thread title is carefully and appropriately worded by it's initiator)
Rocky .. would you please review my last question?

Jimbo

ajj3085 replied on Tuesday, March 27, 2007

Jimbo:
In the UI (form) constructor, BeginEdit is set on the collection object. (standard stuff to initiate csla undo)


Do not call BeginEdit, AcceptEdit or CancelEdit on the collection object.  You must do so on the BindingSource component, so that it can stay 'in the loop.'  Also, I think the grid will automatically call BeginEdit for you as soon as you binding the grid to the BS.

Jimbo:
As at no point did we manually or programatically call Begin, Apply or CancelEdit. Meaning, to most peoples that the edit level should still be at the point that we initiated in the constructor and that all action since would be undone.


The grid will call those methods though, so that may not be true. 

Jimbo:
But this is not the case ... Please explain how we deal with this and achieve the user experience that is expected.


I think as long as you call CancelEdit on the BindingSource, you should get the experience you want.  Doing so will cause the grid to again call BeginEdit I believe though.

Jimbo replied on Tuesday, March 27, 2007

ajj,
I dont know where you are coming from ...
1. your recommendation goes against all that is in the book and the csla application examples.
2. The BindingSource control does not implement BeginEdit or IEditableObject etc.
Show me an example.

Jimbo replied on Tuesday, March 27, 2007

ajj,
Moving on from my previous reply ... You are certainly right that calling CancelEdit on the BindingSource works in this scenario - but only in some cases. It seems to be unreliable if changes/s have been applied programatically to items in the underlying datasource rather than edited individually in the grid. Presumably we have to do something more to notify windows binding (or csla) that the source data has changed and to reset BeginEdit.
But I can still only call BeginEdit on the list (collection) object and am (perhaps) redundantly calling CancelEdit on the list bject


Jimbo

ajj3085 replied on Tuesday, March 27, 2007

Jimbo,

You're right; there's no BeginEdit on the BS, but I think it will call that automatically for you (there is an EndEdit).  As far as going against the book, if you search the forum you'll see that at the time of the writing, Rocky wasn't aware of the problems of not keeping the BS 'in the loop.'  He now recommends you interact only with the binding source.

Now, when you say its unreliable when applying changes programatically.. how are you doing so?  Are you calling EndEdit on the binding source?  If not, you'll run into similar problems.

To successfully use the n-level undo, I think you'll have to keep a 'hands off' approach until you actually want to cancel or accept all changes on the collection... and then you should only do so through the binding source.  Data binding should be calling BeginEdit for you automatically... what are the specific symptoms?  Also, what kind of control are you using?  Different controls from other companies behave in slightly different ways, and don't always interact with databinding as you'd expect.

RockfordLhotka replied on Tuesday, March 27, 2007

I was at a conference last week, and am at a different one this week (and unfortunately got the flu too – bad enough I spent half of today in the hospital L )

 

While flying out to the conferences I did a little testing on this, and my preliminary findings are that the DataGridView calls EndEdit “on your behalf” when the grid loses focus. Of course it loses focus when you click the Cancel button…

 

If your cancel button is on a toolstrip though, then it doesn’t get focus and the issue doesn’t appear to occur.

 

I didn’t post this earlier, because I didn’t get a lot of time to fully explore this effect, but given my past few days, it is clear I won’t get to it until late next week at the earliest. Jimbo, you may want to check on this focus/endedit issue and see if putting your cancel button in a toolstrip solves your issue.

 

Rocky

 

 

From: ajj3085 [mailto:cslanet@lhotka.net]
Sent: Tuesday, March 27, 2007 1:28 PM
To: rocky@lhotka.net
Subject: Re: [CSLA .NET] RE: n-level undo and Windows Forms data binding

 

Jimbo,

You're right; there's no BeginEdit on the BS, but I think it will call that automatically for you (there is an EndEdit).  As far as going against the book, if you search the forum you'll see that at the time of the writing, Rocky wasn't aware of the problems of not keeping the BS 'in the loop.'  He now recommends you interact only with the binding source.

Now, when you say its unreliable when applying changes programatically.. how are you doing so?  Are you calling EndEdit on the binding source?  If not, you'll run into similar problems.

To successfully use the n-level undo, I think you'll have to keep a 'hands off' approach until you actually want to cancel or accept all changes on the collection... and then you should only do so through the binding source.  Data binding should be calling BeginEdit for you automatically.


ajj3085 replied on Tuesday, March 27, 2007

Wow, is that documented somewhere?

RockfordLhotka replied on Wednesday, March 28, 2007

To do my test I just overrode the AcceptChangesComplete and CancelChangesComplete so I could put breakpoints and see the call stack.

 

Interestingly enough – and this is why I was hesitant to talk about this – my Cancel button code DID NOT RUN after that automatic EndEdit. I can’t believe that’s actually the case, so I assume I had a bug in my test …

macu replied on Tuesday, April 10, 2007

I have also problems with DataGridView and undo. I think there is a bug somewhere . How to reproduce it :

1.Open “ProjectTracker20cs”

2.Run PTWin

3. login as pm

4. Edit  “Expert One-on-One VB Business Objects 

5. Change Role in all records

6. Set focus on one record in the grid

7. Press Cancel

 

You will se that only 2 rows did undo operation . One row was unchanged .

macu replied on Sunday, May 06, 2007

Look at this :

 

private void Cancel_Button_Click(object sender, EventArgs e)

    {

       

      this.projectBindingSource.CancelEdit();

      this.resourcesBindingSource.CancelEdit();

      

    }

 

I transformed it to

 

private void Cancel_Button_Click(object sender, EventArgs e)

    {

        this.projectBindingSource.DataSource = typeof(ProjectTracker.Library.Project); ;

        Project.CancelEdit();

        this.projectBindingSource.DataSource = Project;

    }

And noticed that line:

 

this.projectBindingSource.DataSource = Project;

 

calls BeginEdit() twice .

one at:

project.BeginEdit();

second at:

project.resources[0].BeginEdit();

 

this result in situation like this :

name   EditLevel

project        1

  resource1    2

  resource2    1

  resource3    1

 

When we fire undo operation it lower our level by one

 

name   EditLevel

project        0

  resource1    1

  resource2    0

  resource3    0

 

and again there are two calls from binding sources:

 

First:

name   EditLevel

project        1

  resource1    2

  resource2    1

  resource3    1

 

Second:

name   EditLevel

project        1

  resource1    3

  resource2    1

  resource3    1

 

I think that Parent editLevel  and collection editLevel should be  >= resource editlevel . I tried this :

 

this.ResourcesDataGridView.DataSource = typeof(ProjectTracker.Library.ProjectResource);

        ((ProjectTracker.Library.ProjectResource)this.resourcesBindingSource.Current).CancelEdit();

        ((ProjectTracker.Library.ProjectResource)this.resourcesBindingSource.Current).CancelEdit();

        this.projectBindingSource.CancelEdit();

        this.resourcesBindingSource.CancelEdit();

        this.ResourcesDataGridView.DataSource = resourcesBindingSource;

 

On each call:

((ProjectTracker.Library.ProjectResource)this.resourcesBindingSource.Current).CancelEdit();

 

i got BeginEdit() on thesame object so this line does nothing :/

I dont have a clue how to solove this :( .  

 

 

RockfordLhotka replied on Sunday, May 06, 2007

I just discovered this too - the issue (I think) is that there's a bug in the cancel button handler. Notice that the parent bindingsource is canceled before the child - that's wrong. It should be

      this.resourcesBindingSource.CancelEdit();
      this.projectBindingSource.CancelEdit();

 

RockfordLhotka replied on Tuesday, June 12, 2007

It turns out that the real solution is a bit more complex than what's been discussed here. In CSLA .NET 3.0 I added code so objects will refuse to apply/cancel their changes if there's a mismatch between the parent and child edit levels. This revealed some lurking issues with Windows Forms data binding and cancel buttons.

As a result, the new ProjectTracker's PTWin app has corrected code as described in this article.

nagendrad replied on Wednesday, January 17, 2007

RockfordLhotka:
_bindingEdit should only be set to true in the case that BeginEdit was called through the IEditableObject interface.
 
CSLA .NET supports n-level undo. IEditableObject only supports 1 level undo. The _bindingEdit flag exists to allow IEditableObject to do its 1 level of undo by using the pre-existing n-level undo support in CSLA.
 
I discuss this quite a bit in Chapter 3 in the book, I recommend reading through that to get a better understanding of the design tradeoffs involved here.
 
Rocky


From: derfy [mailto:cslanet@lhotka.net]
Sent: Sunday, July 30, 2006 11:32 AM
To: rocky@lhotka.net
Subject: Re: [CSLA .NET] n-level undo and Windows Forms data binding

Hi,

Having made some tests on ProjecTracker, i discovered that when CopyState method
gets called on a collection like projects, for example after a manual or a framework-call BeginEdit,  _bindingEdit is not set to true on the projectresources child objects as i would have been expected. I'm asking if is this the expected behaviour. If not so, is it correct overriding the  CopyStateComplete method on BusinessBase class end setting _bindingEdit to true, there?

I'm just a CLSA newcomer, so forgive me for the silly question, and for my english!

Thanks.




Copyright (c) Marimer LLC