コード例 #1
0
        /// <summary>
        /// Get a list of field filters for export
        /// </summary>
        private void BuildExportTableFilters()
        {
            int    protocolId  = int.Parse(QueryProtocolId);
            string datasetSQL  = CacheManager.GetDatasetSQL(Session[SessionKey.DatasetId]);
            bool   unmaskDates = UnmaskedCheck.Checked;
            // get a list of tables and filters
            Dictionary <string, List <string> > filtersByTable = ProtocolMgmtServices.GetDataExportFilters(datasetSQL, protocolId, unmaskDates);
            IEnumerable <CaisisCheckBoxList>    inputs         = PageUtil.GetControls <CaisisCheckBoxList>(PatientPanel_Filters);

            // data bind checkbox lists to values
            foreach (CaisisCheckBoxList input in inputs)
            {
                if (filtersByTable.ContainsKey(input.Table))
                {
                    // tmp fix
                    input.PreRender += new CaisisEventHandler(input_PreRender);
                    input.DataSource = filtersByTable[input.Table];
                    input.DataBind();
                }
            }
            // static binding for Encounters filter
            string encountersTable = new BOL.Encounter().TableName;
            var    encounterFields = from field in service.GetFieldNames(encountersTable)
                                     let name                         = field.Key
                                                            let label = pdec.GetFieldLabel(encountersTable, name)
                                                                        orderby label ascending
                                                                        select new
            {
                FieldName  = name,
                FieldLabel = label
            };

            Encounters_Filter.DataSource = encounterFields;
            Encounters_Filter.DataBind();
        }
コード例 #2
0
        /// <summary>
        /// Suppress data entry fields for entry
        /// </summary>
        protected void SuppressDataEntry()
        {
            IEnumerable <ICaisisInputControl> inputs  = PageUtil.GetControls <ICaisisInputControl>(Page);
            IEnumerable <IButtonControl>      buttons = PageUtil.GetControls <IButtonControl>(Page);

            // diable caisis input controls
            foreach (ICaisisInputControl input in inputs)
            {
                input.Enabled = false;
            }
            // disable buttons/image buttons
            foreach (IButtonControl button in buttons)
            {
                (button as Control).Visible = false;
            }
        }
コード例 #3
0
ファイル: DynamicPage.cs プロジェクト: aomiit/caisis
        /// <summary>
        /// Adds the child table's data entry input fields for the child table
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void BuildRptrChildDataEntry(object sender, RepeaterItemEventArgs e)
        {
            if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
            {
                // get child table and data
                string childTableName = childTableName = e.Item.DataItem.ToString();
                IEnumerable <IBusinessObject> childRecords = _children[childTableName];
                // locate data entry control
                var childDataEntry = GetChildDataEntry(e.Item);
                // get child input fields
                var childInputFields = GetInputControls(childTableName);
                // build interface
                bool childIsGrid = pdec.IsGridView(childTableName);
                // grid interface
                if (childIsGrid)
                {
                    // add data entry fields interface
                    // important, at least 1 child bizo
                    var childGridRecords = childRecords;
                    // shouldn't ever hit here, blank data populated ??? - ac
                    if (childRecords.Count() == 0)
                    {
                        childRecords = new List <IBusinessObject>()
                        {
                            BusinessObjectFactory.BuildBusinessObject(childTableName)
                        };
                    }
                    CaisisGridView grid = CICHelper.AddGridViewByTableName(childDataEntry, childRecords, childTableName);
                    bool           childRecordsExist = childRecords.Where(c => c.PrimaryKeyHasValue).Count() > 0;
                    grid.VisibleBlankRows = childRecordsExist ? 0 : 1;
                }
                // standard data entry interface
                else
                {
                    var childDataEntryControl = BuildChildDataEntryInterface(childInputFields);
                    // add data entry fields interface
                    childDataEntry.Controls.Add(childDataEntryControl);

                    // set values on inital load
                    if (childRecords.Count() > 0 && !Page.IsPostBack)
                    {
                        IEnumerable <ICaisisInputControl> inputFields = PageUtil.GetControls <ICaisisInputControl>(e.Item);
                        SetFieldValues(childRecords.First(), inputFields);
                    }
                }
            }
        }
コード例 #4
0
ファイル: PatientBaseline.aspx.cs プロジェクト: aomiit/caisis
        /// <summary>
        /// Saves the patient's baseline form
        /// </summary>
        private void SaveBaselineForm()
        {
            var     inputs            = CICHelper.GetCaisisInputControls(BaselineFormPanel);
            var     dataEntryControls = PageUtil.GetControls <BaseDataEntryControl>(BaselineFormPanel);
            int     patientId         = int.Parse(base.BaseDecryptedPatientId);
            Patient patient           = new Patient();

            patient.Get(patientId);
            List <BusinessObject> ancestors = new List <BusinessObject>();

            ancestors.Add(patient);
            foreach (BaseDataEntryControl control in dataEntryControls)
            {
                List <BusinessObject> children = new List <BusinessObject>();
                children.AddRange(control.Save());
            }
        }
コード例 #5
0
        private void BuildNavigationLinks()
        {
            var links = PageUtil.GetControls <HtmlAnchor>(EFormActivityHeader);

            foreach (var link in links)
            {
                string column = link.Title;
                string sort   = "asc";
                if (!string.IsNullOrEmpty(QueryColumn) && QueryColumn == column)
                {
                    if (!string.IsNullOrEmpty(QuerySort) && QuerySort == "asc")
                    {
                        sort = "desc";
                    }
                }
                link.HRef = "AdminEformActivity.aspx?searchDate=" + DateChooser.Text + "&column=" + column + "&sort=" + sort;
            }
        }
コード例 #6
0
        private Dictionary <string, List <Dictionary <string, object> > > GetExportTableRestrictions(IEnumerable <string> tables)
        {
            int    protocolId  = int.Parse(QueryProtocolId);
            string datasetSQL  = CacheManager.GetDatasetSQL(Session[SessionKey.DatasetId]);
            bool   unmaskDates = UnmaskedCheck.Checked;
            // get a list of tables and filters
            Dictionary <string, List <string> > filtersByTable = ProtocolMgmtServices.GetDataExportFilters(datasetSQL, protocolId, unmaskDates);
            Dictionary <string, List <Dictionary <string, object> > > tableToListOfRestrictions = new Dictionary <string, List <Dictionary <string, object> > >();
            IEnumerable <CaisisCheckBoxList> inputs   = PageUtil.GetControls <CaisisCheckBoxList>(PatientPanel_Filters);
            IEnumerable <string>             formKeys = Request.Form.Keys.Cast <string>();

            foreach (CaisisCheckBoxList input in inputs)
            {
                string   formInputName    = input.Table + "_Filter";
                string[] formExcludeNames = new string[] { input.Table + "_FilterCheckBox", input.Table + "_FilterTextBoxKey" };
                // check for values POSTed
                int  selectedCount  = formKeys.Where(k => k.StartsWith(formInputName)).Except(formExcludeNames).Count();
                bool addRestriction = filtersByTable.ContainsKey(input.Table) && selectedCount > 0 ? filtersByTable[input.Table].Count() != selectedCount : false;
                // manually add each restriction if 1-(n-1) items selected
                if (addRestriction)
                {
                    string   table         = input.Table;
                    string   field         = input.Field;
                    string[] field_filters = input.ValueList;
                    if (field_filters.Length > 0)
                    {
                        if (tables.Contains(table))
                        {
                            var filterList = new List <Dictionary <string, object> >();
                            foreach (string field_filter in field_filters)
                            {
                                filterList.Add(new Dictionary <string, object> {
                                    { field, field_filter }
                                });
                            }
                            tableToListOfRestrictions.Add(table, filterList);
                        }
                    }
                }
            }
            return(tableToListOfRestrictions);
        }
コード例 #7
0
ファイル: BaseControl.cs プロジェクト: aomiit/caisis
 /// <summary>
 /// Initialize required variables, i.e., patientId and events
 /// </summary>
 protected void InitControl()
 {
     patientId   = int.Parse(Session[SessionKey.PatientId].ToString());
     isFormDirty = false;
     // track field changes on load
     this.Load += (o, e) =>
     {
         var inputs = PageUtil.GetCaisisInputControlsInContainer(this);
         foreach (var input in inputs)
         {
             input.ValueChanged += MarkFormDirty;
         }
         var grid = PageUtil.GetControls <GridView>(this).Cast <Control>();
         var rptr = PageUtil.GetControls <Repeater>(this).Cast <Control>();;
         var dataBoundComponenets = grid.Concat(rptr);
         foreach (var componenet in dataBoundComponenets)
         {
             InitDirtyControlTracking(componenet);
         }
     };
 }
コード例 #8
0
ファイル: PatientBaseline.aspx.cs プロジェクト: aomiit/caisis
        /// <summary>
        /// Populates the patient's baseline form
        /// </summary>
        private void PopulateBaselineForm()
        {
            int patientId         = int.Parse(BaseDecryptedPatientId);
            int ptProtocolId      = int.Parse(PatientProtocolId);
            var dataEntryControls = PageUtil.GetControls <BaseDataEntryControl>(BaselineFormPanel);
            // load patient
            Patient patient = new Patient();

            patient.Get(patientId);
            // load patient protocol
            PatientProtocol ptProtocol = new PatientProtocol();

            ptProtocol.Get(ptProtocolId);
            PatientProtocolController ptProtocolController = new PatientProtocolController(ptProtocolId);
            DateTime?onStudyDate         = ptProtocolController.GetStatusDate(PatientProtocolController.OnStudy);
            DateTime?screeningFailedDate = ptProtocolController.GetStatusDate(PatientProtocolController.ScreeningFailed);
            DateTime?screeningPassedDate = ptProtocolController.GetStatusDate(PatientProtocolController.ScreeningPassed);
            // determine date ranges
            DateTime?baselineFromDate = null;
            DateTime?baselineToDate   = onStudyDate ?? screeningFailedDate ?? screeningPassedDate;

            List <ICaisisInputControl> inputs = new List <ICaisisInputControl>();

            // populate components
            foreach (BaseDataEntryControl control in dataEntryControls)
            {
                // set date ranges
                control.BaselineFromDate = baselineFromDate;
                // todo???
                control.BaselineToDate = baselineToDate;
                control.Populate();
                inputs.AddRange(CICHelper.GetCaisisInputControls(control));
            }
            // add required field
            foreach (var control in inputs.Where(i => i.Required).OfType <WebControl>())
            {
                control.Attributes["data-required"] = "true";
            }
        }
コード例 #9
0
ファイル: PatientIndex.aspx.cs プロジェクト: aomiit/caisis
        protected override void Page_Load(object sender, EventArgs e)
        {
            base.Page_Load(sender, e);
            bool isSpecimenEnabled = EnableSpecimens(int.Parse(BaseProtocolId));
            // get tab links
            var links = PageUtil.GetControls <HtmlAnchor>(PatientMenuTable);

            // set dynamic url based on current query params
            foreach (var link in links)
            {
                // set url with params
                link.HRef = GetQueryString(link.HRef);
                // default view (non-specimen users see all tabs, specimen users see none)
                link.Visible = true;
                // special case
                if (link == SpecimensTab)
                {
                    // specimen user+enabled
                    if (isSpecimenEnabled)
                    {
                        SpecimensTabCell.Visible = true;
                        link.Visible             = true;
                        // focus on speicmens tab for speicmen users
                        //if (isSpecimenUser)
                        //{
                        //    Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "ENABLE_PROTOCOL_SPECIMENS", "var ENABLE_PROTOCOL_SPECIMENS = true;", true);
                        //}
                    }
                    else
                    {
                        SpecimensTabCell.Visible = false;
                        link.Visible             = false;
                    }
                }
            }
        }
コード例 #10
0
        /// <summary>
        /// For the given eform docuemnt, build client scripts for handling client sider EFromDefaultValue logic.
        /// </summary>
        /// <param name="eformsXml">The Eform document containing EFromDefaultValue mappings</param>
        protected void BuildDefaultValuesScript(XmlDocument eformsXml)
        {
            var eFields = EFormController.GetEformDefaultValues(eformsXml);

            if (eFields.Count() > 0)
            {
                // list of all eform inputs
                IEnumerable <IEformInputField> inputs = PageUtil.GetControls <IEformInputField>(Page);
                // list of eform labels
                IEnumerable <EformDefaultLabel> labels = PageUtil.GetControls <EformDefaultLabel>(Page);
                // create JSON Serialier and list of output objects
                System.Web.Script.Serialization.JavaScriptSerializer serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
                // list of client JSON objects
                List <string> _clientConfigs = new List <string>();
                // temp: fix to empty RecordId's
                Func <string, string, bool> matchRecordIds = (r1, r2) =>
                {
                    return((!string.IsNullOrEmpty(r1) ? r1 : "1") == (!string.IsNullOrEmpty(r2) ? r2 : "1"));
                };
                foreach (var eField in eFields)
                {
                    // FIND INPUTS
                    // i.e., Table=Encounters, RecordId=1
                    var inputsByTableRecordId = inputs.Where(input => input.Table == eField.TargetTable && matchRecordIds(input.RecordId, eField.TargetRecordId));
                    // i.e., Table=Encounters, Field=EncDate, RecordId=1
                    var targetInput = inputsByTableRecordId.Where(input => input.Field == eField.TargetField);
                    // i.e., Table=Encounters, Field!=EncDate, RecordId=1
                    var targetInputSiblings = inputsByTableRecordId.Except(targetInput);
                    // get type of default
                    EFormController.EformDefaultType type = eField.GetDefaultType();
                    if (targetInput.Count() > 0)
                    {
                        // get eform input field
                        IEformInputField targetInputField = targetInput.First();
                        // i.e., find sources by table and record (will be reduced by field, if needed)
                        var sourceInputs = from input in inputs
                                           // validate table
                                           where !string.IsNullOrEmpty(eField.TargetTable)
                                           where input.Table == eField.SourceTable && matchRecordIds(input.RecordId, eField.SourceRecordId)
                                           select input;

                        // get child input fields of target
                        if (eField.TriggeredByChildren)
                        {
                            // i.e. target=Survey.SurveyType,1, children=SurveyItems where ParentRecordId = 1
                            var targetChildInputs = from childTable in BOL.BusinessObject.GetChildTableNames(eField.TargetTable)
                                                    from input in inputs
                                                    where input.Table == childTable && matchRecordIds(input.ParentRecordId, targetInputField.RecordId)
                                                    select input;
                            if (targetChildInputs.Count() > 0)
                            {
                                // TODO: do we just combine sibling and children and rely on side effect ???
                                targetInputSiblings = targetInputSiblings.Concat(targetChildInputs).Distinct();
                            }
                        }

                        // FILTER and VALIDATE
                        bool hasClientFields = true;
                        switch (type)
                        {
                        case EFormController.EformDefaultType.Default:
                            // no source
                            sourceInputs = sourceInputs.Take(0);
                            break;

                        case EFormController.EformDefaultType.SourceDefaultValue:
                            // validate: 1+ source
                            if (sourceInputs.Count() == 0)
                            {
                                hasClientFields = false;
                            }
                            break;

                        case EFormController.EformDefaultType.SourceValue:
                            // validate: only 1 source (match exact Field)
                            sourceInputs = sourceInputs.Where(i => i.Field == eField.SourceField).Take(1);
                            if (sourceInputs.Count() == 0)
                            {
                                hasClientFields = false;
                            }
                            break;

                        // never gets called
                        default:
                            hasClientFields = false;
                            break;
                        }

                        // BUILD: client scripts

                        if (hasClientFields)
                        {
                            // get fields as Control to get client id
                            Control targetInputControl = targetInputField as Control;
                            IEnumerable <Control> targetInputSiblingControls = targetInputSiblings.OfType <Control>();
                            IEnumerable <Control> sourceInputControls        = sourceInputs.OfType <Control>();

                            // BUILD: client JSON
                            var JSONConfig = new
                            {
                                DefaultType     = type.ToString(),
                                DefaultValue    = eField.DefaultValue,
                                Target          = new { Type = targetInputControl.GetType().Name, Id = targetInputControl.ClientID },
                                TargetSiblings  = targetInputSiblingControls.Select(s => new { Type = s.GetType().Name, Id = s.ClientID }),
                                Sources         = sourceInputControls.Select(t => new { Type = t.GetType().Name, Id = t.ClientID }),
                                RequireSiblings = eField.RequireSiblings,
                                TriggerSiblings = eField.TriggeredBySiblings
                            };
                            // serialize object
                            string JSONConfigString = serializer.Serialize(JSONConfig);
                            _clientConfigs.Add(JSONConfigString);
                        }
                    }

                    // BUILD: default labels
                    if (type == EFormController.EformDefaultType.Default)
                    {
                        foreach (var label in labels)
                        {
                            // parse via id
                            if (!string.IsNullOrEmpty(label.DefaultField))
                            {
                                string labelTable    = "";
                                string labelField    = "";
                                string labelRecordId = "";
                                EFormController.EformDefaultValueField.ParseDefaultField(label.DefaultField, ref labelTable, ref labelField, ref labelRecordId);
                                if (eField.TargetTable == labelTable && eField.TargetField == labelField && eField.TargetRecordId == labelRecordId)
                                {
                                    label.Text = eField.DefaultValue;
                                }
                            }
                        }
                    }
                }
                // CLIENT SCRIPT: build and register client script
                if (_clientConfigs.Count() > 0)
                {
                    // serialize list of objects into JSON array for client scripts
                    string configJSONArray = "[" + string.Join(",", _clientConfigs.ToArray()) + "]";

                    // register start up script: validate functions exists
                    string _script = "if(window.initEformDefaultValues) { window.initEformDefaultValues(" + configJSONArray + "); }";
                    Page.ClientScript.RegisterStartupScript(this.GetType(), "initEformDefaultValues_" + this.ClientID, _script, true);
                }
            }
        }
コード例 #11
0
 /// <summary>
 /// Returns a list of each chart on the page
 /// </summary>
 /// <returns></returns>
 public virtual IEnumerable <CaisisChart> GetCharts()
 {
     return(PageUtil.GetControls <CaisisChart>(Page));
 }
コード例 #12
0
ファイル: DynamicPage.cs プロジェクト: aomiit/caisis
        virtual protected void Save(object sender, System.EventArgs e)
        {
            // validation hooks?

            // TODO: we could refactor w/ custom iterators

            // set bizo fields from main fields
            IEnumerable <ICaisisInputControl> controls = CICHelper.GetCaisisInputControls(this);

            SetBizoValues(bizo, controls);

            // set parent fields (if applicable)
            if (parent != null)
            {
                SetBizoValues(parent, controls);
            }

            //foreach (ICaisisInputControl c in controls)
            //{
            //    // validate table and field
            //    if (bizo.TableName == c.Table && bizo.HasField(c.Field))
            //    {
            //        bizo[c.Field] = c.Value;
            //    }
            //}

            string squery = Request.Url.Query;

            squery = this.RemoveParameterFromUrlQueryString(squery, "error");
            squery = this.RemoveParameterFromUrlQueryString(squery, "save");

            string redirectURL = "DynamicForm.aspx" + squery;

            try
            {
                //if (primaryKey > -1)
                //{
                //    model.UpdateRecord();
                //}
                //else
                //{
                //    primaryKey = model.InsertRecord();
                //    redirectURL += "&pkey=" + primaryKey;
                //}

                // save parent (optional)
                if (parent != null)
                {
                    parent.Save();
                    //  update foreign key
                    bizo[bizo.ParentKeyName] = parent[parent.PrimaryKeyName];
                }

                // save main biz
                bizo.Save();

                // save children (optional)
                if (ChildTableNames.Count() > 0)
                {
                    // get child tables rptr
                    Repeater childTablesRptr = Page.FindControl("ChildTablesRptr") as Repeater;

                    // get required parent key
                    string parentTableName = bizo.TableName;
                    string parentKeyName   = bizo.PrimaryKeyName;
                    int    parentPriKey    = (int)bizo[bizo.PrimaryKeyName];

                    // save each child table
                    foreach (RepeaterItem rptrItem in childTablesRptr.Items)
                    {
                        HiddenField tableNameField = rptrItem.FindControl("TableNameField") as HiddenField;
                        if (tableNameField != null && !string.IsNullOrEmpty(tableNameField.Value))
                        {
                            string childTableName = tableNameField.Value;
                            bool   isGrid         = pdec.IsGridView(childTableName);
                            // validate: child table and "dirty" (!important: grid has own tracking)
                            if (ChildTableNames.Contains(childTableName) && (isGrid || isTableDirty.ContainsKey(childTableName)))
                            {
                                // grid tables
                                if (isGrid)
                                {
                                    // locate child grid
                                    var childTableGrid = PageUtil.GetControls <CaisisGridView>(rptrItem).FirstOrDefault();
                                    // should only by 1 grid per child table
                                    if (childTableGrid != null)
                                    {
                                        childTableGrid.Save();
                                    }
                                }
                                // standard data entry tables
                                else
                                {
                                    var             inputFields = PageUtil.GetControls <ICaisisInputControl>(rptrItem);
                                    IBusinessObject childBizo;
                                    // update
                                    if (_children.ContainsKey(childTableName) && _children[childTableName].Count() > 0)
                                    {
                                        childBizo = _children[childTableName].First();
                                    }
                                    // insert
                                    else
                                    {
                                        childBizo = BusinessObjectFactory.BuildBusinessObject(childTableName);
                                        // set parent key
                                        childBizo[parentKeyName] = parentPriKey;
                                    }
                                    // set field values
                                    SetBizoValues(childBizo, inputFields);
                                    // update/save
                                    childBizo.Save();
                                }
                            }
                        }
                    }
                }

                if (!redirectURL.Contains("pkey="))
                {
                    redirectURL += "&pkey=" + bizo[bizo.PrimaryKeyName].ToString();
                }

                redirectURL += "&saved=true";
            }
            catch (Exception ex)
            {
                // TODO: we can parse exception for more detail ...

                //if (ex is ClientException)
                //{
                //    string field = ex.Message;
                //    DataRow row = model.GetHelpFieldInfo(field);

                //    // we need to map this field to metadata
                //    redirectURL += "&error=" + row["FieldLabel"].ToString();
                //}
                //else
                //{
                redirectURL += "&error=_default";

                // let everyone know
                ExceptionHandler.Publish(ex);
                //}
            }

            Response.Redirect(redirectURL);
            // added saved=true, should prob move that portion at later date - jf
        }
コード例 #13
0
ファイル: DynamicPage.cs プロジェクト: aomiit/caisis
        virtual protected void Page_Load(object sender, System.EventArgs e)
        {
            bool   retrieveValues = false;
            string pks            = Request["pkey"];

            if (pks != null && pks.Length > 0)
            {
                primaryKey = int.Parse(pks);
                //v4.0 model = new DynamicModel(tableName, primaryKey, patientID, new ValidateNullsDelegate(NullsValidatorWrapper.ValidateNullsHaveData));
                // model = new DynamicModel();

                bizo = BusinessObjectFactory.BuildBusinessObject(tableName);
                bizo.Get(primaryKey);

                retrieveValues = true;

                // peek at the lockedby
                if (bizo.HasField(BusinessObject.LockedBy))
                {
                    if (bizo[BusinessObject.LockedBy] != null && !string.IsNullOrEmpty(bizo[BusinessObject.LockedBy].ToString()))
                    {
                        recordIsLocked = true;
                    }
                }
            }
            else
            {
                //v4.0 model = new DynamicModel(tableName, patientID, new ValidateNullsDelegate(NullsValidatorWrapper.ValidateNullsHaveData));
                // model = new DynamicModel();

                bizo = BusinessObjectFactory.BuildBusinessObject(tableName);

                // is this necessary?
                if (bizo.HasField("PatientId"))
                {
                    bizo["PatientId"] = patientID;
                }
            }

            // set parent biz
            if (bizo != null)
            {
                // LOAD OPTIONAL PARENT TABLE

                // verify has parent which isn't Patient
                if (!string.IsNullOrEmpty(bizo.ParentTableName) && bizo.ParentTableName != "Patients")
                {
                    // validate no multiple foreign keys
                    if (bizo.ForeignKeyNames.Count() == 1 && !bizo.ForeignKeyNames.Contains(Patient.PatientId))
                    {
                        var pBiz = BusinessObjectFactory.BuildBusinessObject(bizo.ParentTableName);
                        // one last verification
                        if (!(pBiz is Patient))
                        {
                            parent = pBiz;
                            // load parent biz if applicable
                            if (bizo.PrimaryKeyHasValue)
                            {
                                int parPriKey = (int)bizo[bizo.ParentKeyName];
                                parent.Get(parPriKey);
                            }
                        }
                    }
                }
                // LOAD CHILD TABLES
                if (ChildTableNames.Length > 0)
                {
                    // rebuild child table lookup
                    _children = new Dictionary <string, IEnumerable <IBusinessObject> >();

                    int parentKey = (int)bizo[bizo.PrimaryKeyName];
                    // build lookup: child table -> child records
                    var childTableNames     = ChildTableNames.Where(t => BusinessObject.GetParentTablename(t) == bizo.TableName);
                    var childTableToRecords = childTableNames.ToDictionary(t => t, t => BusinessObject.GetByParent(t, parentKey));

                    // validation: validate children
                    foreach (var child in childTableToRecords)
                    {
                        string childTable = child.Key;
                        IEnumerable <IBusinessObject> childBizos = child.Value;

                        // if child is grid with no record, create blank data
                        bool isGrid = pdec.IsGridView(childTable);
                        if (isGrid && childBizos.Count() == 0)
                        {
                            // init blank rows
                            childBizos = new IBusinessObject[] { BusinessObjectFactory.BuildBusinessObject(childTable) };
                            // set parent key
                            foreach (var b in childBizos)
                            {
                                b[b.ParentKeyName] = parentKey;
                            }
                        }
                        // add entry
                        _children.Add(childTable, childBizos);
                    }
                }
            }

            if (Page.IsPostBack)
            {
                BuildControls(bizo, false);
            }
            else
            {
                BuildControls(bizo, retrieveValues);
            }
            // init field-tracking: note late bound binding
            foreach (var input in PageUtil.GetControls <ICaisisInputControl>(Page))
            {
                input.ValueChanged += MarkTableFieldsDirty;
            }
        }