Edit Level Mismatch AND Object Still Being Edited and Can't be saved

Edit Level Mismatch AND Object Still Being Edited and Can't be saved

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


st3fanus posted on Saturday, September 15, 2012

Hi all..

 

I don't have an understanding what problem i faced.

This my scenario :

I Have a view model for my root view model ( DomainEditGetterVM ), in this vm I have a view model as root's view model property which is I used for my view ( DomainEditVM ).

SO, in the DomainEditVM I'm not load my DomainEdit BO by BeginRefresh BUT I received it from constructor like this :

public DomainEditVM(DomainEdit model, DomainEditGetterVM parent)
        {
            Model = model;
            Parent = parent
            //  ManageObjectLifetime = false;

..........................................

        }

 

AND THEN in this ( DomainEditVM ) I have a method which is call BeginSave();

 

The Error Raise :

1. Edit Level Mismatch When I Comment ManageObjectLifetime = false

2. AND WHEN I Uncomment ManageObjectLifetime = true, THERE IS ANOTHER ERROR :

    Object Still Being Edited and Can't be saved

 

Could Anyone Give Me suggestions or explain me what i should to do ?

 

thanks a lot

 

stefanus

JonnyBee replied on Saturday, September 15, 2012

Only "root" viewmodel (or the TopMost VM that has ManageObjectLifetime=true and has a "root" business object) can save the business object.

When the VM has ManageObjectLifetme it will also take responsibility for calling BeginEdit/ApplyEdit/CancelEdit and handle Save.
You should NOT mix this in different VievModels.

In this case - your DomainEditGetterVM should have ManageObjectLifetime = false and you should set the Model on DomainEditVM using the DependencyProperty.

From ViewModelBase:

 

    public static readonly DependencyProperty ModelProperty =

        DependencyProperty.Register("Model", typeof(T), typeof(ViewModelBase<T>),

#if NETFX_CORE

        new PropertyMetadata(default(T), (o, e) =>

#else

        new PropertyMetadata((o, e) =>

#endif

        {

          var viewmodel = (ViewModelBase<T>)o;

          viewmodel.OnModelChanged((T)e.OldValue, (T)e.NewValue);

          if (viewmodel.ManageObjectLifetime)

          {

            var undo = e.NewValue as Csla.Core.ISupportUndo;

            if (undo != null)

              undo.BeginEdit();

          }

        }));

 

st3fanus replied on Saturday, September 15, 2012

Hi Jonny.. thanks for your quick respons

 

But I still not yet got your explanation,  Do you  mean I must add that code on My DomainEditVM or on my ViewModelBase Class ?

And Why I Can't just call BeginSave() from my DomainEditVM ?

What information I must know about this topic ? Because I have faced a similar problem and i just set ManageLifetime = false in order I can run BeginSave()

BUT I don't the consequence about my action I just confuse Because I can't save my Business Object.

 

I really thanks for you help jonny

 

Stefanus

JonnyBee replied on Sunday, September 16, 2012

My understanding of your problem is that DomainEditGetterVM has ManageObjectLifetime = true.
IF SO: Then this is the VM that should call Save.

My suggestion is that you set ManageObjectLifetime = false on the DomainEditGetterVM and set ManageObjectLifetime = true on DomainEditVM .

And you should use the Model dependency property on DomainEditVM or in you contstructor - you must make sure to call BeginEdit on the BO.
The DomainEditVM must be in charge on the BO in order to call Save.

st3fanus replied on Sunday, September 16, 2012

Hi jonny

I'm glad to see you in this thread again :)

 

Yes you are right that is my condition, BUT I have tried your suggestions :

1. I have set ManageObjectLifetime =  false on DomainEditGetterVM

2. I have set ManageObjectLifetime = true on DomainEditVM, BECAUSE in this view model I run BeginSave();

BUT the problem still arise "Edit Level Mismatch Accept Changes"

 

SO, if that error is caused by the BeginEdit number DIFFERENCE with ApplyEdit() or CancelEdit() number.

THEN as long as I'm aware of , I don't call BeginEdit() or ApplyEdit() anywhere in my code.

 

SECOND, If that is the real problem WHEN I set ManageObjectLifetime = false on DomainEditVM THEN It's must be no error, BUT What I got is an error that said : "Object is still being edit can't saved"

 

SO I don't have an understanding what happen here ?

 

And For Addtional information :

My DomainEdit Business Object Has Child Collection which is bound to DataGrid in View , Is this an posibility association with this problem ?

And If yes, Could you help me with those posibility i must check ?

 

 

thanks a lot jonny

stefanus

JonnyBee replied on Sunday, September 16, 2012

You must check EditLevel on your root object.

After ApplyEdit is called the entire graph should be at editlevel = 0.
The Save exception is thrown in BusinessBase.Save:

    public virtual T Save()
    {
      T result;
      if (this.IsChild)
        throw new InvalidOperationException(Resources.NoSaveChildException);
      if (EditLevel > 0)
        throw new InvalidOperationException(Resources.NoSaveEditingException);

      if (!IsValid && !IsDeleted)
        throw new Rules.ValidationException(Resources.NoSaveInvalidException);
      if (IsBusy)
        throw new InvalidOperationException(Resources.BusyObjectsMayNotBeSaved);
      if (IsDirty)
        result = (T)DataPortal.Update(this);
      else
        result = (T)this;
      OnSaved(result, null, null);
      return result;
    }

st3fanus replied on Sunday, September 16, 2012

Hi jonny

 

Where do I must check EditLevel ?

actually I don't know how to do your suggestion ( Check EditLevel )

 

thanks a lot jonny

JonnyBee replied on Sunday, September 16, 2012

EditLevel is a "state" property on the BO.

st3fanus replied on Sunday, September 16, 2012

Yes jonny

But, I can't access it from DomainEditVM

with Model.EditLevel , AM I right ?

 

 

JonnyBee replied on Sunday, September 16, 2012

Editlevel is in the IUndoableObject interface or you can add your own public property MyEditLevel to expose it from the BO .

Like:

public int MyEditLevel
{
     get  { return base.EditLevel; }
}

or

((IUndoableObject) Model).EditLevel

st3fanus replied on Sunday, September 16, 2012

Hi jonny

Good Morning, Thanks for your helper so far..

 

Yes jonny you are right , I have Check EditLevel on DomainEdit BO on DomainEditVM

I got EditLevel is 4.

 

SO , What are they which caused the value of EditLevel ( DomainEdit ) is 4 ?

Or What I have to check or inspect later after this ?

 

Note :

This is the structure of My Entire Business Object

DomainEdit => DomainClasses => DomainClassEdit => DomainStudents => DomainStudentEdit

AND I bound DomainClasses with DataGrid ?

 

thanks jonny

 

 

st3fanus replied on Monday, September 17, 2012

HI jonny

 

I have checked EditLevel

And I got like this :

My BO structure :

 

DomainEdit => DomainClasses => DomainEdit => DomainStudents => DomainStudentEdit

 

I have tried to check each edit level AND The result is :

 

DomainEdit  => level 4

DomainClasses => Level 4

DomainEdit => Level 5

DomainStudents => Level 5

DomainStudentEdit is not yet filled with BO

 

So, this is look like that there is somewhere a trigger to call beginEdit in my BusinessObject Structures , BUT I don't have enough knowledge, WHERE ?

Is this problem is asscoicated with DataGrid which is I bound with my DomainClasses ?

 

thanks jonny..

 

richardb replied on Monday, September 17, 2012

Grid control could be firing BeginEdit's automatically - depends on the control, how you are using it, etc.

Make sure when you do the save that you Unbind and Rebind to your data control.

st3fanus replied on Monday, September 17, 2012

Hi richard.. thanks for your respons

 

1. So How Do I can Know The DataGrid Work ?

2. How I can UnBind and Rebind on DataGrid Silverlight ?

thanks a lot

 

 

Copyright (c) Marimer LLC