CancelEdit and ListChanged event

Posts   
 
    
TheSwiss
User
Posts: 35
Joined: 05-Apr-2005
# Posted on: 07-Apr-2005 19:06:43   

Hi,

another databinding issue: It appears that entitycollection fires the listchanged event when a field is modified, but before the row is commited in a grid. When I cancel the enitire row edit (ESC), the values are reset, but no second listChanged event ist fired. So my GUI essentially thinks, the row is changed although it's not.

So Ive taken a look at the source code - and voil - EntityBase2.CancelEdit() appears not to fire any event, while EntityBase2.SetNewFieldValue() obviously fires FlagMeAsChanged() when (_editCycleInProgress && !_isNew) evaluates to true and the value has been changed.

So since CancelEdit() does not call SetNewFieldValue, not event is fired.

Is it possible to a) fire the event in both cases (then I have at least a chance to track it with some overhead, when actually nothing is changed, or even better b) to fire the event only after editing the row is commited?

Thanks for any comments

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 07-Apr-2005 20:34:19   

TheSwiss wrote:

Hi,

another databinding issue: It appears that entitycollection fires the listchanged event when a field is modified, but before the row is commited in a grid. When I cancel the enitire row edit (ESC), the values are reset, but no second listChanged event ist fired. So my GUI essentially thinks, the row is changed although it's not.

So Ive taken a look at the source code - and voil - EntityBase2.CancelEdit() appears not to fire any event, while EntityBase2.SetNewFieldValue() obviously fires FlagMeAsChanged() when (_editCycleInProgress && !_isNew) evaluates to true and the value has been changed.

So since CancelEdit() does not call SetNewFieldValue, not event is fired.

Is it possible to a) fire the event in both cases (then I have at least a chance to track it with some overhead, when actually nothing is changed, or even better b) to fire the event only after editing the row is commited?

Thanks for any comments

I don't think that's how it works (but I might misunderstand databinding's internal core goo wink ). As the user presses ESC, the IEditableObject.CancelEdit method is called, which means: any change should be rolled back. This means that the Currencymanager knows that the row is not changed, but its initial state. Firing another event would IMHO signal something which isn't true: there is nothing changed, compared to its initial value.

The event has to be fired immediately to keep stuff in sync.

Frans Bouma | Lead developer LLBLGen Pro
TheSwiss
User
Posts: 35
Joined: 05-Apr-2005
# Posted on: 07-Apr-2005 23:56:10   

Otis wrote:

I don't think that's how it works (but I might misunderstand databinding's internal core goo wink ). As the user presses ESC, the IEditableObject.CancelEdit method is called, which means: any change should be rolled back. This means that the Currencymanager knows that the row is not changed, but its initial state. Firing another event would IMHO signal something which isn't true: there is nothing changed, compared to its initial value.

The event has to be fired immediately to keep stuff in sync.

Yeah, I see the conflict... but how can i track if an item in an EntityCollection, that is, a row in a datagrid, is changed AND committed. As you say, EntityCollection.ListChanged doesn't help, because it doesn't imply that an initial change is not rolled back. Help... frowning flushed

TheSwiss
User
Posts: 35
Joined: 05-Apr-2005
# Posted on: 09-Apr-2005 13:04:57   

erm... don't wanna be nagging, but is there a way to track that? HELP...!

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 09-Apr-2005 15:00:49   

TheSwiss wrote:

erm... don't wanna be nagging, but is there a way to track that? HELP...!

No, because why would you want to?

Frans Bouma | Lead developer LLBLGen Pro
TheSwiss
User
Posts: 35
Joined: 05-Apr-2005
# Posted on: 09-Apr-2005 17:56:02   

Otis wrote:

TheSwiss wrote:

erm... don't wanna be nagging, but is there a way to track that? HELP...!

No, because why would you want to?

UI design. Display all modified entities of a collection to the user in a second grid. So I should get an event that signals to me, when an entitiy has been modified and commited. Isn't that a pretty general requirement? I could also wanna change the font or the background color of modified rows... maybe I'm totally missing something, but at the moment I don't see it. Any ideas?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 09-Apr-2005 19:06:07   

You can grab the dirty entities in a collection by using entitycollection.DirtyEntities. (Adapter).

Frans Bouma | Lead developer LLBLGen Pro
TheSwiss
User
Posts: 35
Joined: 05-Apr-2005
# Posted on: 09-Apr-2005 20:13:48   

Otis wrote:

You can grab the dirty entities in a collection by using entitycollection.DirtyEntities. (Adapter).

Sure, I can actively access that ArrayList and check if it has changed. But it doesn't expose any events, either. So the issue remains: When the user tries to change a field value in a grid, I get an event. However, when the change is rolled back by ESC, I can't track that, because I don't get any notification that the change is taken back, not even a second ListChanged event. What I do get in this case, is one ListChanged event although after the rollback, the list isn't event changed, but in it's original state. I was thinking of some mechanism like the one implemented in DataTable: it exposes RowChanging AND RowChanged events (well, and the same for columns and for deletes, but from my egoistic point of view, I only need the row change related stuff...). Hmm, was I just implicitly praising microsoft? frowning sorry for that, but I think I have a point in my reasoning. IMHO, two events do not only make sense in combination with a grid, but are way more than just a convenience. Or is there any other decent way to make the kind of tracking I described work? Again: help!

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 10-Apr-2005 13:16:57   

I'm not saying you're wrong, as you aren't, though there is something we've to live with I think and that's how databinding works. The reason I fire the Changed event the second some field changes and not when the EndEdit method is called, is because of simple binding (i.e. with textboxes): there, EndEdit for the ROW is NEVER called. So if you bind the 10 fields of an entity to 10 textboxes, you won't see changes if I don't fire the changed events directly. (IEditableObject calls BeginEdit twice: once for the entire object and once for the field being edited)

This behavior creates this wicked situation. Because now the academic discussion has to be held: "when is an entity changed?". Is that: 1) when a field's value is different at point T+n from the value it had at point T or 2) when a field's value is different at point T' from the value it had at point T

1) defines that the change is always later in time but compared to the original. So if I do: T: load entity E T+1: SaveFields T+2: E.Foo = somevalue T+3: E is now considered changed T+4: Rollback fields T+5: E now is considered the same and unchanged as no field has a different value as it had on T

2) defines that the change is always later in time but compared to the previous time spot. So the previous situation differs on T+5: T: load entity E T+1: SaveFields T+2: E.Foo = somevalue T+3: E is now considered changed T+4: Rollback fields T+5: E is still considered changed because T+5 differs from T+4

Now, for editing INSIDE an edit cycle (BeginEdit -> change a value -> EndEdit) 1) is used. Though between 2 edit cycles (initial value is 0, you change it to 1, move on to another row, come back to the cell, change it back to 0) this is equal to 2).

Rolling back fields to a previous save, is that 1) or 2)? You could argue 2), but what if the values are the same? Then it's a 1). Do you want the events in that case? No not likely. But is that possible to find out? Well with 1 SaveFields -> RollbackFields, it is, but with 10 SaveFields in a row, it's not. As the RollbackFields call still might result in changed fields compared with the 2nd SaveFields in the row of 10 times SavedFields.

RollbackFields now fires ALL fieldChanged events and the entity is changed event. And I think that's good. It fires the EntityContentsChanged event. You can bind to that event. You then know if something is changed. But what you WANT IMHO is that you DON'T get that event in the situation where it's a 1) but I can't do that.

So, a RollbackFields will result in a changed event for the entity, i.e. a 2). Because RollbackFields rolls back the complete Fields object, which contains if the entity was in fact dirty, you can then determine if the entity was changed since the beginning (entity.IsDirty==true) or not (entity.IsDirty==false). I think with these 2 elements you can accomplish what you want. simple_smile

(oh, and I know that looking at that IsDirty flag could make RollbackFields able to determine if it actually has to fire changed events, but that's not always true, as the IsChanged flags and IsDirty flag can be manipulated in code. )

Frans Bouma | Lead developer LLBLGen Pro