EditLevel Problem with Databinding

EditLevel Problem with Databinding

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


wjcomeaux posted on Tuesday, August 19, 2008

Hello all:

I've read various forums here on issues that occur when databinding RootLists to DataGridViews. I seem to be having pretty much the same issues described in those posts but, so far, none of the fixes seem to be working for me.

I started out with version 3.0.4 of the framework I upgraded to 3.5.1 this morning. I get different errors with the different versions.

With both versions I get EditLevel mismatch errors but in different places.

Scenario: TaxNotice_EditableRootList bound to a datagridview.

Each TaxNotice_EditableChild contains a TaxNoticeAction_EditableRootList which is bound to a second grid.

I have turned off AllowUserToAddRows and AllowUserToDeleteRows for both grids ( I perform adds and deletes through context menus).

There is a listbox that causes the initial datagrid (TaxNotices) to load for the selected Employer. The TaxNotices grid causes the TaxNoticeActions grid to display it's data (through the SelectionChanged event).

On SelectedIndexChanged of the listbox I do this

RebindUI(false, false);

_selectedEmployerID = int.Parse(payrollEmployer_RORLListBox.SelectedValue.ToString());

selectedPayrollEmployerTaxNotice_ERL = PayrollEmployerTaxNotice_ERL.GetPayrollEmployerTaxNotice_ERL(_selectedEmployerID);

BindUI();

My BindUI and RebindUI functions are based on the PTracker project except I've substituted my own objects.

After the above code has executed my EditLevels look like this

selectedTaxNotice_EditableRootList ---- 1

selectedTaxNotice_EditableRootList[0] ---- 2

selectedTaxNotice_EditableRootList[0].TaxNoticeAction_EditableRootList ----- 1

selectedTaxNotice_EditableRootList[0].TaxNoticeAction_EditableRootList[0] ----- 2

Previously with the older version I was not able to add new items to selectedTaxNotice_EditableRootList but other edits and cancels to existing items worked. However, with the latest version of CSLA I can add and then cancel new TaxNotice objects however, if I Add then edit the new item and then click cancel or save I get an EditLevel mismatch in CopyState error.

I will post the relevant parts of my code below. The business objects were all generated with CodeSmith. Sorry about the formatting if this doesn't turn out nicely. And TIA for reading!

Will

protected void FormMain_Load(object sender, EventArgs e)

{

taxSpecialist_NVLBindingSource.DataSource = Hps.Business.TaxSpecialist_NVL.GetTaxSpecialist_NVL();

payrollEmployerTaxNoticeActionType_NVLBindingSource.DataSource = _payrollEmployerTaxNoticeActionType_NVL;

payrollEmployerTaxType_NVLBindingSource.DataSource = _payrollEmployerTaxType_NVL;

}

///This is what causes the main grid to refresh

private void payrollEmployer_RORLListBox_SelectedIndexChanged(object sender, EventArgs e)

{

RebindUI(false, false);

_selectedEmployerID = int.Parse(payrollEmployer_RORLListBox.SelectedValue.ToString());

selectedPayrollEmployerTaxNotice_ERL = PayrollEmployerTaxNotice_ERL.GetPayrollEmployerTaxNotice_ERL(_selectedEmployerID);

BindUI();

}

private void btnSave_Click(object sender, EventArgs e)

{RebindUI(true, true);}

private void btnCancel_Click(object sender, EventArgs e)

{RebindUI(false, true);}

protected void AddNewTaxNotice(object sender, EventArgs e)

{

if (selectedPayrollEmployerTaxNotice_ERL != null)

{

if (!selectedPayrollEmployerTaxNotice_ERL.IsDirty)

{

selectedPayrollEmployerTaxNotice_EC = selectedPayrollEmployerTaxNotice_ERL.AddNew();

selectedPayrollEmployerTaxNotice_EC.EmployerOID = _selectedEmployerID;

PayrollEmployerTaxNoticeAction_EC newPayrollEmployerTaxNoticeAction_EC = selectedPayrollEmployerTaxNotice_EC.PayrollEmployerTaxNoticeAction_ERL.AddNew();

newPayrollEmployerTaxNoticeAction_EC.Description = "Tax Notice Opened";

newPayrollEmployerTaxNoticeAction_EC.PayrollEmployerTaxNoticeActionTypeID = _payrollEmployerTaxNoticeActionType_NVL.GetItemByValue("Opened").Key;

payrollEmployerTaxNotice_ERLBindingSource.ResetBindings(false);

}

else

{

MessageBox.Show("You currently have pending changes in an existing tax notice. Please save or cancel those changes before adding a new tax notice", "Unsaved Changes", MessageBoxButtons.OK);

}}}

 

 

private void BindUI()

{

selectedPayrollEmployerTaxNotice_ERL.BeginEdit();

payrollEmployerTaxNotice_ERLBindingSource.DataSource = selectedPayrollEmployerTaxNotice_ERL;

}

private void RebindUI(bool saveObject, bool rebind)

{

// disable events

this.payrollEmployerTaxNoticeAction_ERLBindingSource.RaiseListChangedEvents = false;

this.payrollEmployerTaxNotice_ERLBindingSource.RaiseListChangedEvents = false;

try

{

// unbind the UI

UnbindBindingSource(this.payrollEmployerTaxNoticeAction_ERLBindingSource, saveObject, false);

UnbindBindingSource(this.payrollEmployerTaxNotice_ERLBindingSource, saveObject, true);

//this.AssignmentsBindingSource.DataSource = this.ResourceBindingSource;

// save or cancel changes

if (saveObject)

{

if (selectedPayrollEmployerTaxNotice_ERL != null)

{

selectedPayrollEmployerTaxNotice_ERL.ApplyEdit();

try

{

selectedPayrollEmployerTaxNotice_ERL = selectedPayrollEmployerTaxNotice_ERL.Save();

}

catch (Csla.DataPortalException ex)

{

MessageBox.Show(ex.BusinessException.ToString(), "Error saving", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);

}

catch (Exception ex)

{

MessageBox.Show(ex.ToString(), "Error Saving", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);

}}}

else

{

if (selectedPayrollEmployerTaxNotice_ERL != null)

{

selectedPayrollEmployerTaxNotice_ERL.CancelEdit();

}}}

finally

{

// rebind UI if requested

if (rebind)

BindUI();

// restore events

this.payrollEmployerTaxNotice_ERLBindingSource.RaiseListChangedEvents = true;

this.payrollEmployerTaxNoticeAction_ERLBindingSource.RaiseListChangedEvents = true;

if (rebind)

{

// refresh the UI if rebinding

this.payrollEmployerTaxNotice_ERLBindingSource.ResetBindings(false);

this.payrollEmployerTaxNoticeAction_ERLBindingSource.ResetBindings(false);

}}}

protected void UnbindBindingSource(BindingSource source, bool apply, bool isRoot)

{

System.ComponentModel.IEditableObject current = source.Current as System.ComponentModel.IEditableObject;

if (isRoot)

{

source.DataSource = null;

}

if (current != null)

{

if (apply)

{current.EndEdit();}

else

{current.CancelEdit();}

}}

wjcomeaux replied on Wednesday, August 20, 2008

Anyone? This is really driving me up the wall. Not to mention oncoming deadlines.

For those not wanting to read the entire post below the gist is this. I am getting EditLevel mismatches when databinding to DataGridViews using the latest (and previous) version of CSLA and business objects generated with CodeSmith.

Depending on which version of CSLA I use I get different errors. I've followed everything that's been posted on this forum so far, unless I'm missing something.

Any input is much appreciated.

Thanks,

Will

RockfordLhotka replied on Wednesday, August 20, 2008

The problem is probably something in your UI code. It is possible there yet another bug in CSLA in this regard, but I think we've finally found them all (and by "we" I mean people on this forum, like yourself, who've done a ton of research).

You should compare your UI code to this sample:

http://www.lhotka.net/cslacvs/viewvc.cgi/samples/trunk/RootChildGrandchildWinFormTest/

This is my core test for data binding. It works on 3.0.4 and 3.5.1 (and 3.6).

wjcomeaux replied on Monday, August 25, 2008

Hey Rocky. Thanks for the reply. I'm still having troubles. As far as I can tell, the only difference between our code is that you are using the property manager in your business objects and I am not. Could this be the cause of the problem? I am still getting EditLevel mismatch errors at different points.

For instance, if I click on my employer list (to cause the TaxNotice (root) and TaxNoticeAction (child) grids to load then immediately click cancel (without performing any edits) I get this error. I have stepped all the way down into the code  and the error happes in line 258 of UndoableBase

((Core.IUndoableObject)value).UndoChanges(this.EditLevel, BindingEdit); In this case "this.EditLevel" = 0 and "BindingEdit" = false.

This call is made from the block of code inside"foreach (FieldInfo field in fields)" and the field in question is my TaxNoticeAction_EditableRootList (my child object -- actually collection of objects).

Any thoughts? I've pasted the entirety of my FormMain code below in case you want to load it into a code window and take a look. It's pretty simple stuff.

Thanks,

Will

 

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

using Csla;

using Hps.Business;

namespace Hps.Windows.Applications.Enterprise.Modules.TaxNoticeManager

{

public partial class FormMain : Form

{

private int _selectedEmployerID;

private FilteredBindingList<Hps.Business.PayrollEmployer_RORL> _payrollEmployer_FilteredBindingList;

private PayrollEmployerTaxNotice_ERL selectedPayrollEmployerTaxNotice_ERL;

private PayrollEmployerTaxNotice_EC selectedPayrollEmployerTaxNotice_EC;

private ContextMenu _contextMenuForTaxNoticeDataGridView = new ContextMenu();

private PayrollEmployerTaxNoticeActionType_NVL _payrollEmployerTaxNoticeActionType_NVL = PayrollEmployerTaxNoticeActionType_NVL.GetPayrollEmployerTaxNoticeActionType_NVL();

private PayrollEmployerTaxType_NVL _payrollEmployerTaxType_NVL = PayrollEmployerTaxType_NVL.GetPayrollEmployerTaxType_NVL();

public FormMain()

{

InitializeComponent();

}

protected void FormMain_Load(object sender, EventArgs e)

{

taxSpecialist_NVLBindingSource_ForGrid.DataSource = Hps.Business.TaxSpecialist_NVL.GetTaxSpecialist_NVL();

cboFilterTaxSpecialist.Items.Add(new Csla.NameValueListBase<int, string>.NameValuePair(0, "Any"));

foreach (Csla.NameValueListBase<int, string>.NameValuePair item in TaxSpecialist_NVL.GetTaxSpecialist_NVL())

{

cboFilterTaxSpecialist.Items.Add(item);

}

payrollEmployerTaxNoticeActionType_NVLBindingSource.DataSource = _payrollEmployerTaxNoticeActionType_NVL;

payrollEmployerTaxType_NVLBindingSource.DataSource = _payrollEmployerTaxType_NVL;

}

protected void payrollEmployerTaxNotice_ERLBindingSource_CurrentChanged(object sender, EventArgs e)

{

payrollEmployerTaxNoticeAction_ERLBindingSource.EndEdit();

}

private void payrollEmployer_RORLListBox_SelectedIndexChanged(object sender, EventArgs e)

{

if (payrollEmployer_RORLListBox.SelectedValue != null)

{

_selectedEmployerID = int.Parse(payrollEmployer_RORLListBox.SelectedValue.ToString());

selectedPayrollEmployerTaxNotice_ERL = PayrollEmployerTaxNotice_ERL.GetPayrollEmployerTaxNotice_ERL(_selectedEmployerID);

BindUI(selectedPayrollEmployerTaxNotice_ERL);

}

}

protected void CloseTaxNotice(object sender, EventArgs e)

{

selectedPayrollEmployerTaxNotice_EC.CloseTaxNotice();

}

protected void ReOpenTaxNotice(object sender, EventArgs e)

{

selectedPayrollEmployerTaxNotice_EC.ReOpenTaxNotice();

}

protected void AddNewTaxNotice(object sender, EventArgs e)

{

if (selectedPayrollEmployerTaxNotice_ERL != null)

{

if (!selectedPayrollEmployerTaxNotice_ERL.IsDirty)

{

selectedPayrollEmployerTaxNotice_EC = selectedPayrollEmployerTaxNotice_ERL.AddNew();

selectedPayrollEmployerTaxNotice_EC.EmployerOID = _selectedEmployerID;

PayrollEmployerTaxNoticeAction_EC newPayrollEmployerTaxNoticeAction_EC = selectedPayrollEmployerTaxNotice_EC.PayrollEmployerTaxNoticeAction_ERL.AddNew();

newPayrollEmployerTaxNoticeAction_EC.Description = "Tax Notice Opened";

newPayrollEmployerTaxNoticeAction_EC.PayrollEmployerTaxNoticeActionTypeID = _payrollEmployerTaxNoticeActionType_NVL.GetItemByValue("Opened").Key;

payrollEmployerTaxNotice_ERLBindingSource.ResetBindings(false);

}

else

{

MessageBox.Show("You currently have pending changes in an existing tax notice. Please save or cancel those changes before adding a new tax notice", "Unsaved Changes", MessageBoxButtons.OK);

}

}

}

protected void AddNewAction(object sender, EventArgs e)

{

if (selectedPayrollEmployerTaxNotice_EC != null)

{

PayrollEmployerTaxNoticeAction_EC newPayrollEmployerTaxNoticeAction_EC = selectedPayrollEmployerTaxNotice_EC.PayrollEmployerTaxNoticeAction_ERL.AddNew();

payrollEmployerTaxNoticeAction_ERLBindingSource.ResetBindings(false);

}

}

protected void payrollEmployerTaxNotice_ERLDataGridView_MouseUp(object sender, MouseEventArgs e)

{

// Load context menu on right mouse click

DataGridView.HitTestInfo hitTestInfo;

if (e.Button == MouseButtons.Right)

{

hitTestInfo = payrollEmployerTaxNotice_ERLDataGridView.HitTest(e.X, e.Y);

if (hitTestInfo.Type == DataGridViewHitTestType.ColumnHeader)

{

_contextMenuForTaxNoticeDataGridView.MenuItems.Clear();

_contextMenuForTaxNoticeDataGridView.MenuItems.Add("Add New Tax Notice", new EventHandler(AddNewTaxNotice));

_contextMenuForTaxNoticeDataGridView.Show(payrollEmployerTaxNotice_ERLDataGridView, new Point(e.X, e.Y));

}

if (hitTestInfo.Type == DataGridViewHitTestType.Cell)

{

PayrollEmployerTaxNotice_EC notice = (PayrollEmployerTaxNotice_EC)payrollEmployerTaxNotice_ERLBindingSource.Current;

if (notice.IsOpenTaxNotice)

{

_contextMenuForTaxNoticeDataGridView.MenuItems.Clear();

_contextMenuForTaxNoticeDataGridView.MenuItems.Add("Close Tax Notice", new EventHandler(CloseTaxNotice));

_contextMenuForTaxNoticeDataGridView.Show(payrollEmployerTaxNotice_ERLDataGridView, new Point(e.X, e.Y));

}

else

{

_contextMenuForTaxNoticeDataGridView.MenuItems.Clear();

_contextMenuForTaxNoticeDataGridView.MenuItems.Add("ReOpen Tax Notice", new EventHandler(ReOpenTaxNotice));

_contextMenuForTaxNoticeDataGridView.Show(payrollEmployerTaxNotice_ERLDataGridView, new Point(e.X, e.Y));

}

}

}

else if (e.Button == MouseButtons.Left)

{

if (payrollEmployerTaxNotice_ERLDataGridView.CurrentRow != null)

{

if (payrollEmployerTaxNotice_ERLDataGridView.Columns[payrollEmployerTaxNotice_ERLDataGridView.CurrentCell.ColumnIndex].Name == "AddComment")

{

commentTextBox.Left = e.X;

commentTextBox.Top = e.Y + 50;

commentTextBox.Text = string.Empty;

commentTextBox.Show();

commentTextBox.Focus();

}

}

}

}

protected void commentTextbox_LostFocus(object sender, EventArgs e)

{

if (commentTextBox.Text != string.Empty)

{

selectedPayrollEmployerTaxNotice_EC.AddComment(commentTextBox.Text, (int)Security.CurrentUser.CurrentIdentity.User.EmployeeID.Value);

commentTextBox.Text = string.Empty;

}

commentTextBox.Hide();

}

protected void payrollEmployerTaxNotice_ERLDataGridView_DataError(object sender, DataGridViewDataErrorEventArgs e)

{

}

protected void payrollEmployerTaxNotice_ERLDataGridView_SelectionChanged(object sender, EventArgs e)

{

try

{

selectedPayrollEmployerTaxNotice_EC = (Hps.Business.PayrollEmployerTaxNotice_EC)payrollEmployerTaxNotice_ERLDataGridView.CurrentRow.DataBoundItem;

if (selectedPayrollEmployerTaxNotice_EC != null)

{

payrollEmployerTaxNoticeAction_ERLBindingSource.DataSource = selectedPayrollEmployerTaxNotice_EC.PayrollEmployerTaxNoticeAction_ERL;

payrollEmployerTaxNoticeAction_ERLBindingSource.ResetBindings(false);

payrollEmployerTaxNoticeAction_ERLDataGridView.Enabled = true;

}

else

{

this.payrollEmployerTaxNoticeAction_ERLDataGridView.Enabled = false;

}

}

catch (Exception ex)

{

}

}

protected void payrollEmployerTaxNoticeAction_ERLDataGridView_DataError(object sender, DataGridViewDataErrorEventArgs e)

{

}

protected void cboFilterTaxSpecialist_SelectedIndexChanged(object sender, EventArgs e)

{

ApplyEmployeeFilter();

}

protected void Search_KeyPress(object sender, KeyPressEventArgs e)

{

if (e.KeyChar == '\r')

{

ApplyEmployeeFilter();

}

}

private void btnApplyEmployerFilter_Click(object sender, EventArgs e)

{

ApplyEmployeeFilter();

}

private void ApplyEmployeeFilter()

{

if (cboFilterTaxSpecialist.SelectedIndex > 0)

{

payrollEmployer_RORLBindingSource.DataSource = Hps.Business.PayrollEmployer_RORL.GetPayrollEmployer_RORL(txtFilterMerchantName.Text, txtFilterMerchantNumber.Text, ((Csla.NameValueListBase<int, string>.NameValuePair)cboFilterTaxSpecialist.SelectedItem).Key);

}

else

{

payrollEmployer_RORLBindingSource.DataSource = Hps.Business.PayrollEmployer_RORL.GetPayrollEmployer_RORL(txtFilterMerchantName.Text, txtFilterMerchantNumber.Text, 0);

}

}

private void btnSave_Click(object sender, EventArgs e)

{

this.payrollEmployerTaxNoticeAction_ERLBindingSource.RaiseListChangedEvents = false;

this.payrollEmployerTaxNotice_ERLBindingSource.RaiseListChangedEvents = false;

PayrollEmployerTaxNotice_ERL payrollEmployerTaxNotice_ERL = (PayrollEmployerTaxNotice_ERL)this.payrollEmployerTaxNotice_ERLBindingSource.DataSource;

UnbindBindingSource(this.payrollEmployerTaxNoticeAction_ERLBindingSource, true);

UnbindBindingSource(this.payrollEmployerTaxNotice_ERLBindingSource, true);

this.payrollEmployerTaxNoticeAction_ERLBindingSource.EndEdit();

this.payrollEmployerTaxNotice_ERLBindingSource.EndEdit();

if (payrollEmployerTaxNotice_ERL != null)

{

payrollEmployerTaxNotice_ERL.ApplyEdit();

BindUI(payrollEmployerTaxNotice_ERL);

}

}

private void btnCancel_Click(object sender, EventArgs e)

{

this.payrollEmployerTaxNoticeAction_ERLBindingSource.EndEdit();

this.payrollEmployerTaxNoticeAction_ERLBindingSource.RaiseListChangedEvents = false;

this.payrollEmployerTaxNotice_ERLBindingSource.RaiseListChangedEvents = false;

PayrollEmployerTaxNotice_ERL payrollEmployerTaxNotice_ERL = (PayrollEmployerTaxNotice_ERL)this.payrollEmployerTaxNotice_ERLBindingSource.DataSource;

UnbindBindingSource(this.payrollEmployerTaxNoticeAction_ERLBindingSource, false);

UnbindBindingSource(this.payrollEmployerTaxNotice_ERLBindingSource, false);

if (payrollEmployerTaxNotice_ERL != null)

{

payrollEmployerTaxNotice_ERL.CancelEdit();

BindUI(payrollEmployerTaxNotice_ERL);

}

}

private void BindUI(PayrollEmployerTaxNotice_ERL payrollEmployerTaxNoticeAction_ERL)

{

payrollEmployerTaxNoticeAction_ERL.BeginEdit();

this.payrollEmployerTaxNotice_ERLBindingSource.DataSource = payrollEmployerTaxNoticeAction_ERL;

this.payrollEmployerTaxNoticeAction_ERLBindingSource.RaiseListChangedEvents = true;

this.payrollEmployerTaxNotice_ERLBindingSource.RaiseListChangedEvents = true;

this.payrollEmployerTaxNoticeAction_ERLBindingSource.ResetBindings(false);

this.payrollEmployerTaxNotice_ERLBindingSource.ResetBindings(false);

}

protected void UnbindBindingSource(BindingSource source, bool apply)

{

System.ComponentModel.IEditableObject current = source.Current as System.ComponentModel.IEditableObject;

if (!(source.DataSource is BindingSource))

{

source.DataSource = null;

}

if (current != null)

{

if (apply)

{

current.EndEdit();

}

else

{

current.CancelEdit();

}

}

}

}

}

wjcomeaux replied on Tuesday, August 26, 2008

Ok, I've rewritten the application to be pretty much just like the sample you provided. What I've done is added a root object (PayrollEmployee as editable root).

PayrollEmployee has an EditableRootList called PayrollEmployeeTaxNotice_ERL

PayrollEmployeeTaxNotice has an EditableRootList called PayrollEmployeeTaxNoticeAction_ERL

I've wired up my grids the same way yours is using a binding source tied to PayrollEmployer, a binding source tied to the PayrollEmployerTaxNotice property of the PayrollEmployer binding source and a binding source tied to the PayrollEmployerTaxNoticeAction property of the PayrollEmployerTaxNotice binding source.

Outside of the names "root", "children" and "grandchildren" we have the same code on our form and I still get errors with EditLevel mismatch.

At this point I can only think it's because my business objects are generated using the C# 2.0 templates and not the C# 3.5 templates which manage all of the properties differently.

Wasn't this functionality all available in CSLA 2.0? And ideas if I'm doing something wrong?

Thanks,

Will

ajj3085 replied on Tuesday, August 26, 2008

Ok, something is jumping out at me now.  You sayd that PayrollEmployee has an ERL, and so does PayrollExmployeeTaxNotice.  ERL should NEVER be contained within another business object.  It fills one very specific nitch; to allow users to edit a grid in which each row within the grid is a root object, and committed independently of the other items in the list.  As soon as the grid calls ApplyEdit, the row being edited is Saved by Csla.  The other objects in the list are independent.

It sounds like you should have your ERL actually subclass BusinessListBase, and they should be marked as a child object because they are contained within another instance that is also editable.

wjcomeaux replied on Tuesday, August 26, 2008

Well, the reason for using EditableRootLists instead of EditableChildLists is the templates provide gets for EditableChildLists by dataReader only. In reality, my parent object has an ID which I then use to get the list of child objects. I don't return then as separate datatable objects.

I can write the filter criteria as part of my editable child list objects but it's code I was trying to not write since it seems like an object with a property that happens to be an Editable Root List would still be treated as a child when it comes to managing the EditLevel.

Will

RockfordLhotka replied on Tuesday, August 26, 2008

ERLB (dynamic lists) can never be child objects. They are a root list of root objects, and are designed to fill a very specific niche: editing in a Windows Forms (or WPF or Silverlight) grid control such that the user’s changes are committed as the user exits each row. Use of ERLB outside this scenario is not supported, and often just won’t work.

 

ERLB doesn’t participate in undo as a child, because it is not designed to ever be a child.

 

If you want a list of editable child objects, you must use BusinessListBase to create an editable list of those objects. That’s the only model that works.

 

Rocky

 

 

From: wjcomeaux [mailto:cslanet@lhotka.net]
Sent: Tuesday, August 26, 2008 1:59 PM
To: rocky@lhotka.net
Subject: Re: [CSLA .NET] EditLevel Problem with Databinding

 

Well, the reason for using EditableRootLists instead of EditableChildLists is the templates provide gets for EditableChildLists by dataReader only. In reality, my parent object has an ID which I then use to get the list of child objects. I don't return then as separate datatable objects.

I can write the filter criteria as part of my editable child list objects but it's code I was trying to not write since it seems like an object with a property that happens to be an Editable Root List would still be treated as a child when it comes to managing the EditLevel.

Will



wjcomeaux replied on Tuesday, August 26, 2008

Ok, thanks guys.  I'm working on the changes now.

Will

Copyright (c) Marimer LLC