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
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(); }
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.
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?
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
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:
I have implemented code like your alternative and it seems to work fine.
Thanks for your help.
Bruno
Copyright (c) Marimer LLC