Bug in Undo: Edit level mismatch in CopyState in version cslacs-3.0.4-080222

Bug in Undo: Edit level mismatch in CopyState in version cslacs-3.0.4-080222

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


alef posted on Saturday, February 23, 2008

I've the following situation

Model : Editable Root Parent (e.g. Shoe123)

ModelColors : EditableChildList (e.g. we have two items black, gold)

ModelColor : EditableChild

Articles : EditableChildList (e.g.

Article : EditableChild

                  Barcode: 2000000001029 ,Size: 36  Price: 88 EUR, Color: black

                  Barcode: 2000000001036 ,Size: 37  Price: 88 EUR, Color: black

                  Barcode: 2000000001043 ,Size: 36  Price: 99EUR, Color: gold

                  Barcode: 2000000001050 ,Size: 37  Price: 99 EUR, Color: gold

 

In the following case I receive the error : Edit level mismatch in CopyState

Edit e.g. the first record for the first color (Barcode: 2000000001029 ,Size: 36  Price: 88 EUR, Color: black)

Click Cancel. Until now everything goes fine.

Edit e.g. the first record for the second color ( Barcode: 2000000001043 ,Size: 36  Price: 99EUR, Color: gold)

Click Cancel. Now I receive the error.

I've implemented the code as in the project tracker example.

I've tested it first with version : 3.0.2 and there I have also the same problem.

I've tested it also with version cslacs-3.0.4-080222 and I have the same problem.

 

Below you can find the code for the method RebindUI:

Until one level I don't have any problems, but now I have two levels:

Parent, ChildCollection, GrandChildCollection

and since then I'm having problems.

I now you have to be carefull in the order you unbind. So that's the reason I've included the code.

Can you have a look at it?

private void RebindUI(bool saveObject, bool rebind)

{

// disable events

this.modelBindingSource.RaiseListChangedEvents = false;

this.modelColorsBindingSource.RaiseListChangedEvents = false;

this.articlesBindingSource.RaiseListChangedEvents = false;

try

{

// unbind the UI

UnbindBindingSource(this.articlesBindingSource, saveObject, false);

UnbindBindingSource(this.modelColorsBindingSource, saveObject, false);

UnbindBindingSource(this.modelBindingSource, saveObject, true);

this.modelColorsBindingSource.DataSource = this.modelBindingSource;

this.articlesBindingSource.DataSource = this.modelColorsBindingSource;

// save or cancel changes

if (saveObject)

{

_model.ApplyEdit();

try

{

Model temp = _model.Clone();

_model = temp.Save();

}

catch (Csla.DataPortalException ex)

{

MessageBox.Show(ex.BusinessException.ToString(),

"Error saving", MessageBoxButtons.OK,

MessageBoxIcon.Exclamation);

}

catch (Exception ex)

{

MessageBox.Show(ex.ToString(),

"Error Saving", MessageBoxButtons.OK,

MessageBoxIcon.Exclamation);

}

}

else

_model.CancelEdit();

// rebind UI if requested

if (rebind)

BindUI();

}

finally

{

// restore events

this.modelBindingSource.RaiseListChangedEvents = true;

this.modelColorsBindingSource.RaiseListChangedEvents = true;

this.articlesBindingSource.RaiseListChangedEvents = true;

if (rebind)

{

// refresh the UI if rebinding

this.modelBindingSource.ResetBindings(false);

this.modelColorsBindingSource.ResetBindings(false);

this.articlesBindingSource.ResetBindings(false);

}

}

}

RockfordLhotka replied on Monday, February 25, 2008

Look at the code from this sample:

http://www.lhotka.net/cslacvs/viewvc.cgi/samples/trunk/RootChildGrandchildWinFormTest/

This sample is a little test project I put together around data binding to grandchild objects, and it might be helpful to you. You can also pull the code completely from the repository if you'd like.

alef replied on Tuesday, February 26, 2008

I've looked at your example. Great, I didn't know that you have created a new example. I knew only about the deepdata example.

I've studied your example and I found the magic line of code which solves the problem:

void childrenBindingSource_CurrentChanged(object sender, EventArgs e)

{

this.grandchildrenBindingSource.EndEdit();

}

In your ProjectTracker example you don't have this.

Rocky. Can you explain a bit more the reason of this? Is it not possible to put this in the framework?

As workaround I had found the following solution:

public Grandchild()

{

DisableIEditableObject = true;

...

}

With this the GUI doesn't have to do anything. But maybe you know some disadvantages for this implementation?

Some remarks:

1) I had to initialize the variable _name to string.Empty otherwise the example is not working

string _name = string.Empty;

2)

Creating a new root doesn't work. You can click on the + on the navigator, but saving and cancelling doesn't work.

 

 

RockfordLhotka replied on Sunday, March 02, 2008

It is the responsibility of the UI (data binding really) to call the IEditableObject interface appropriately. Unfortunately data binding doesn’t seem to handle grandchild objects particularly well, because it doesn’t cascade the EndEdit calls down like you’d expect.

 

In fact, data binding doesn’t provide any indication that currency has changed at the grandchild level (it does at the child level oddly) and so something needs to handle that. Since the business layer isn’t even notified of such a currency change, I don’t know of a way to automate this within CSLA itself.

 

What you are doing with DisableIEditableObject works because you are blocking data binding from doing its BeginEdit. That is probably fine as long as your users don’t expect to be able to use in-place editing in a grid for those grandchild objects. Some things won’t work with this setting - most obviously having the user press ESC to undo changes in a row, but there could be others – I’m not sure.

 

Rocky

 

 

From: alef [mailto:cslanet@lhotka.net]
Sent: Tuesday, February 26, 2008 9:47 AM
To: rocky@lhotka.net
Subject: Re: [CSLA .NET] Bug in Undo: Edit level mismatch in CopyState in version cslacs-3.0.4-080222

 

I've looked at your example. Great, I didn't know that you have created a new example. I knew only about the deepdata example.

I've studied your example and I found the magic line of code which solves the problem:

void childrenBindingSource_CurrentChanged(object sender, EventArgs e)

{

this.grandchildrenBindingSource.EndEdit();

}

In your ProjectTracker example you don't have this.

Rocky. Can you explain a bit more the reason of this? Is it not possible to put this in the framework?

As workaround I had found the following solution:

public Grandchild()

{

DisableIEditableObject = true;

...

}

With this the GUI doesn't have to do anything. But maybe you know some disadvantages for this implementation?

Some remarks:

1) I had to initialize the variable _name to string.Empty otherwise the example is not working

string _name = string.Empty;

2)

Creating a new root doesn't work. You can click on the + on the navigator, but saving and cancelling doesn't work.

 

 



alef replied on Monday, March 03, 2008

Thanks for the explanation.

In the VB world I tried to avoid the binding as much as possible. I thought in .NET everything is solved, but apparently not. Oh the binding stays a tough issue.

In the following case I still have a problem with the example (besides the problems I explained in the previous mail):

delete a child object

click on cancel

You'll receive the error "Edit level mismatch in CopyState".

Rocky, do you now the magic line of code to solve this?

 

 

 

RockfordLhotka replied on Monday, March 03, 2008

Data binding has its quirks - no doubt about it. But there is a such a huge code savings by using data binding compared to doing it yourself (and I don't know that you can replacate in-place grid editing without data binding in any case), that it is worth figuring out.

Your edit level mismatch exception is due to some asymmetry. Every BeginEdit call must have a corresponding CancelEdit/EndEdit. You are just missing one somewhere.

alef replied on Monday, March 03, 2008

I detected that your example was still using version 3.0.2.

I've upgraded it to cslacs-3.0.4-080222 and then I don't have this problem anymore.

Great.

You changed something to solve this, because I didn't changed anything in your example code?

 

RockfordLhotka replied on Monday, March 03, 2008

Probably. I know there were a couple data binding fixes in 3.0.3 and 3.0.4 (see the change logs) and it is quite likely that one of them addressed this issue.

 

Rocky

 

 

From: alef [mailto:cslanet@lhotka.net]
Sent: Monday, March 03, 2008 9:05 AM
To: rocky@lhotka.net
Subject: Re: [CSLA .NET] RE: Bug in Undo: Edit level mismatch in CopyState in version cslacs-3.0.4-080222

 

I detected that your example was still using version 3.0.2.

I've upgraded it to cslacs-3.0.4-080222 and then I don't have this problem anymore.

Great.

You changed something to solve this, because I didn't changed anything in your example code?

 



Copyright (c) Marimer LLC