Using EditableRootList/EditableChild with datagrid

Using EditableRootList/EditableChild with datagrid

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


bdeluard posted on Wednesday, November 21, 2012

Hello,

i'm using DevExpress UI components for SL5. With DynamicRootList/DynamicRoot, all works well.

I have another scenario where I want to defer saving objects in the list to a process called by a button. So I changed my classes to use EditableRootList/EditableChild. When I try to insert a line in the grid, I have an exception saying "List item must be marked as a child object".

I found in the source that the child object is not marked at its creation to be a child objet. I tried to write a default constructor in the EditableChild class which call "MarkAsChild ()" => result is no more exception...

My questions are: is it normal? Is there a better solution (because this new constructor is called each time an object is necessary, not only in my new scenario)?

Thanks in advance,

Bruno

 

JonnyBee replied on Wednesday, November 21, 2012

Your EditableChild should override Child_Create method.

    protected override void Child_Create()
    {
       MarkAsChild();
base.Child_Create();     }

One might argue that the base.Child_Create method should call MarkAsChild - however the existing code is:

    protected virtual void Child_Create()     {       BusinessRules.CheckRules();     }

bdeluard replied on Wednesday, November 21, 2012

I tried your solution, but it seems not to work : I encapsulate the code in a #if SILVERLIGHT directive, but in the debugger it never stops in it. To compile, I had to change the protected attribute to public attribute.

 

JonnyBee replied on Wednesday, November 21, 2012

Normally - if control is performing properly with DataBinding - the <list>.AddNew () method should be called from the grid.

This will in turn call <list>.AddNewCore() and end up i DataPortal.CreateChild.

The actual code doing the work is in ChildDataPortal and is like this:

    private object Create(System.Type objectType, bool hasParameters, params object[] parameters)
    {
      LateBoundObject obj = null;
      IDataPortalTarget target = null;
      var eventArgs = new DataPortalEventArgs(null, objectType, parameters, DataPortalOperations.Create);
      try
      {
        // create an instance of the business object
        obj = new LateBoundObject(objectType);
 
        target = obj.Instance as IDataPortalTarget;
 
        if (target != null)
        {
          target.Child_OnDataPortalInvoke(eventArgs);
          target.MarkAsChild();
          target.MarkNew();
        }
        else
        {
          obj.CallMethodIfImplemented("Child_OnDataPortalInvoke",
            eventArgs);
          obj.CallMethodIfImplemented("MarkAsChild");
          obj.CallMethodIfImplemented("MarkNew");
        }
 
 
        // tell the business object to create its data
        if (hasParameters)
          obj.CallMethod("Child_Create", parameters);
        else
          obj.CallMethod("Child_Create");
 
        if (target != null)
          target.Child_OnDataPortalInvokeComplete(eventArgs);
        else
          obj.CallMethodIfImplemented("Child_OnDataPortalInvokeComplete",
            eventArgs);
 
        // return the populated business object as a result
        return obj.Instance;
 
      }

Which should take care of calling both Child_Create, MarkAsChild and MarkNew.

So - how do add a new item to the list?

Does your code call <list>.AddNew() or is it the datagrid control
that does not follow databinding rules?

bdeluard replied on Wednesday, November 21, 2012

Thanks for your time for me!

It seems that it's the control which do not call the <list>AddNew() method... If I have well understand things during debugging, it's the InsertItem(...) method which is called. I modified it to call a new method in the child class which calls only the MarkAsChild() method, and all works fine.

At the beginning, I had some problems with same things when generating my DynamicList/DynamicRoot and concluded that AddNew() is not called, and InsertItem() was called at the place.

I will ask information at the DevExpress support team, to know how the list is used.

Thanks for your help!

Bruno

JonnyBee replied on Thursday, November 22, 2012

There is no standard AddNew() method without parameters:

Collection<T>.Add(T)
ObservableCollection<T>.InsertItem(int, T)
IList.Add(object)

So you may need to find a way to override the default behavior to call list.AddNew() or make changes to your child object so it is always a Child object.

Another alternative is to:

bdeluard replied on Thursday, November 22, 2012

I have implemented code like your alternative and it seems to work fine.

Thanks for your help.

Bruno

 

Copyright (c) Marimer LLC