Workaround for IsDirty == false after removing newly added child

Workaround for IsDirty == false after removing newly added child

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


Michael posted on Wednesday, January 13, 2010

Hi everyone

We are developing a CAD product with CSLA which saves the business objects to the database when the drawing is saved.

So, it's possible to edit an object, add a new child object to the object's child collection, accept the changes and have the drawing updated accordingly. Then if you edit the object and delete the child, the parent object becomes not
IsSavable, as expected, because from the data point of view, there's now nothing to save.

My problem is, in my edit screens when OK is clicked I use the
IsSavable flag to determine whether to ApplyEdit() or CancelEdit(). Obviously, this doesn't work in this case, because the object now appears to be not IsDirty, the edit is cancelled and the child object comes back.

One hacky solution is to expose a
HasDeletedItems in the BLB and override the parent's IsDirty:

public override bool IsDirty
{
    get { return base.IsDirty || Children.HasDeletedItems; }
}


But, is there a better way?

Kind regards
Michael

rsbaker0 replied on Wednesday, January 13, 2010

Interesting problem.

I think of ISavable as applying more to where or not you should call Save() rather than accept or undo any changes made to the object.

My instinct would be to unconditionally ApplyEdit() when OK is pressed. If a user wants to cancel and edit, then they they would push a Cancel button.

Incidentally, ApplyEdit() is comparatively more expensive than CancelEdit() since it just discards the top of the Undo state stack while CancelEdit() applies all the values in the state to the object. There seems little harm in ApplyEdit() if the object is not dirty, so perhaps you could just ApplyEdit() if the object was either IsSavable or !IsDirty.

Michael replied on Wednesday, January 13, 2010

Thanks for the reply.

I find that users don't much like hitting Cancel, even if they haven't changed anything. But, the main reason I've approached it this way is because if and only if something really has changed, the object needs to be redrawn in AutoCAD, and that can take up to 500ms for some objects. Draftsmen are very impatient; they already complain that 350ms is too long for a dialog to display (which is mostly the time taken for databinding to complete - I have no idea how to speed this up).

ajj3085 replied on Thursday, January 14, 2010

I think the simpliest solution is to bind your OK button to IsValid.  You want to allow users to click OK even if there are no changes, but (I assume) not if the object is valid.

Only if IsSavable is true would you do the apply edit.

If data binding is hurting performance, probably the only thing you can do is not use databinding.  It uses reflection, which is slow.  But then you'll have to write all the plumbing code yourself.

JonnyBee replied on Thursday, January 14, 2010

Hi,

Which version of Csla are you using and do you use "managed properties" in your root object?

If you are using "managed properties" this should be handled automatically by fieldmanager.




tmg4340 replied on Thursday, January 14, 2010

Why not override "IsSavable" to reflect what you need it to be?  The method is virtual, so you could pull the code into your subclasses and do what you need to with the "IsDirty" check there.

- Scott

rxelizondo replied on Thursday, January 14, 2010


I personally would't override anything, I would simply create my brand new property that would be exclusively used for my your particular need.

public override bool CADNeedsRedraw
{
get { return base.IsDirty || Children.HasDeletedItems; }
}

tmg4340 replied on Thursday, January 14, 2010

But then I'd argue that if Rocky didn't want the "IsSavable" functionality to be modified, then he wouldn't have made the method virtual.  Smile [:)]

Honestly, it doesn't matter to me.  I just see "IsSavable" as a piece of information that may not be 100% the same for every object (which is also why I think Rocky made the method virtual).  But if you want to leave that alone and make a different property - or if the concepts are logically different for you - then by all means, make a different property and bind to that.

- Scott

rxelizondo replied on Thursday, January 14, 2010

I am cool with that but really, the only reason I suggested to create a new property was because in my head, I feel that overriding the property the way the OP is doing will give the property a different meaning to it.

I mean, I guess that what I am trying to say is that he is coercing that property into being something it was not design to be. He is using the property to determine something it was not design to determine.... did I just repeated myself :)

Trying to determine if he should redraw his screen or not using the IsSavable property? Its just feels wrong to me, but this is just my opinion of course.

Any way, it really does not matter to me either. Life is good!

Thanks.

Rene

Michael replied on Thursday, January 14, 2010

The OK button is enabled as follows:
OKEnabled = BusinessObject.IsSavable || !BusinessObject.IsDirty;

Jonny, I'm using 3.7 currently, and I am using managed properties for the child collections. My problem is that IsDirty is false after removing the new child. I just wondered if there was a simpler way to discover this.

Rene, I see your point about a separate property. I agree it's a better approach than to change the behaviour of IsDirty or IsSavable.

I'm happy enough with this solution now. Thanks everyone!

Copyright (c) Marimer LLC