ApplyEdit -- don't understand why it's needed in this case

ApplyEdit -- don't understand why it's needed in this case

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


artsd posted on Wednesday, June 02, 2010

Using Silverlight client, I have a root editable parent object (Client) who owns a single child object (Blob). Blob has a byte[] property BlobAsImage which stores JPEG data.

I have a XAML page using the CslaDataProvider to bind to Client. Binding to regular properties of Client like FirstName and LastName works fine -- I can create new and make changes using a trigger button that calls Save on the CslaDataProvider.

Now I added an Image control that binds to Client.Blob.BlobAsImage (really the image control is binding to Client.Blob but I have a converter that gets the bits from Blob.BlobAsImage). This works fine.

I added a button to clear the image. This is where the problem begins. Here is the button handler that clears the image bits.

        private void Clear_Picture_Click(object sender, RoutedEventArgs e)
        {
            Csla.Xaml.CslaDataProvider dp = Resources["data"] as Csla.Xaml.CslaDataProvider;
            if (dp != null)
            {
                Lib.Client client = dp.ObjectInstance as Lib.Client;
                if (client != null && client.Blob != null)
                {
                    client.Blob.BlobAsImage = null;
                    // ----- why do I need this ---- client.ApplyEdit();
                    dp.Rebind();
                }
            }
        }

If I don't do the client.ApplyEdit() call, I get the "object is still being edited and can not be saved" error when saving using CslaDataProvider's Save.

I don't understand what caused the BeginEdit()?

RockfordLhotka replied on Wednesday, June 02, 2010

As you probably know, CslaDataProvider will automatically leverage n-level undo if its ManageObjectLifetime property is true (which it is by default). Normally that's automatic - you never see it.

In your case I am not sure what is going on, or how you've implemented the Blob and BlobAsImage properties.

So Blob is a child object - that means its edit level is also elevated automatically, and should be 1 as this code is running. I assume BlobAsImage is a standard CSLA property, so it uses GetProperty/SetProperty to get/set the value and properly raise PropertyChanged and all that good stuff? And the property is of type byte[]?

Maybe you can isolate this into a simple unit test? If it is an n-level undo issue, the problem would exhibit itself without CslaDataProvider. Basically you should be able to write a console app something like this:

var client = ...;

client.BeginEdit()

client.Blob.BlobAsImage = null;

client.ApplyEdit();

client = client.Save();

and that should cause the same exception. That'd help with troubleshooting, as it removes all the other complexity that might exist.

artsd replied on Friday, June 04, 2010

I got the problem solved but not exactly sure how. I made the simple unit test and it worked fine so I guessed it had something to do with the way I was using data binding / data provider.

Originally, the datacontext for the root level grid container was the CslaDataProvider which returned the Client object. The Image was bound to Blob which is a child object owned by Client. I then had an image converter that got the image bits from Blob.BlobAsImage which is the byte[] storing the jpeg. In button handler to clear image bits, I had to Rebind() the CslaDataProvider in order for the image to clear.

I changed it so the Image was in a stack panel with its datacontext set to Blob and then the image is bound to BlobAsImage instead of Blob. My converter then just used byte[] directly instead of casting object to Blob and getting BlobAsImage from it.

With that change, it all worked as expected including Cancel support which restores the image to its original picture.

I guess I was originally breaking something by not binding to BlobAsImage but modifying it anyway.

Thanks.

Copyright (c) Marimer LLC