private static void PrepareCodeletsPrimaryKey(
            TTable ACurrentTable,
            out string csvListPrimaryKeyFields,
            out string formalParametersPrimaryKey,
            out string actualParametersPrimaryKey,
            out Tuple <string, string, string>[] formalParametersPrimaryKeySeparate)
        {
            csvListPrimaryKeyFields    = "";
            formalParametersPrimaryKey = "";
            actualParametersPrimaryKey = "";
            int           counterPrimaryKeyField = 0;
            string        PrimaryKeyLabel;
            List <string> PrimaryKeyLabels = new List <string>();

            if (!ACurrentTable.HasPrimaryKey())
            {
                formalParametersPrimaryKeySeparate = new Tuple <string, string, string> [0];
                return;
            }

            formalParametersPrimaryKeySeparate = new Tuple <string, string, string> [ACurrentTable.GetPrimaryKey().strThisFields.Count];

            foreach (string field in ACurrentTable.GetPrimaryKey().strThisFields)
            {
                if (counterPrimaryKeyField > 0)
                {
                    csvListPrimaryKeyFields    += ",";
                    formalParametersPrimaryKey += ", ";
                    actualParametersPrimaryKey += ", ";
                }

                TTableField typedField = ACurrentTable.GetField(field);

                PrimaryKeyLabel = typedField.strLabel;

                // Ensure that a table definition doesn't contain Primary Key columns with identical Labels as this would lead
                // to generated cascading count code that would fail at runtime as it would want to add items with the same
                // name to the 'PKInfo' dictionary! (Those labels would be wrong anyhow!)
                if (!PrimaryKeyLabels.Contains(PrimaryKeyLabel))
                {
                    PrimaryKeyLabels.Add(PrimaryKeyLabel);
                }
                else
                {
                    throw new Exception(
                              String.Format(
                                  "The DB table definition of Table '{0}' in petra.xml contains two Columns with the same Label, '{1}'. That is not allowed!",
                                  ACurrentTable.strName, PrimaryKeyLabel));
                }

                csvListPrimaryKeyFields    += field;
                formalParametersPrimaryKey += typedField.GetDotNetType() + " A" + TTable.NiceFieldName(field);
                actualParametersPrimaryKey += "A" + TTable.NiceFieldName(field);

                formalParametersPrimaryKeySeparate[counterPrimaryKeyField] = new Tuple <string, string, string>(
                    typedField.GetDotNetType(), " A" + TTable.NiceFieldName(field), PrimaryKeyLabel);

                counterPrimaryKeyField++;
            }
        }
        /// <summary>
        /// get formal and actual parameters for a unique or primary key
        /// </summary>
        /// <param name="ACurrentTable"></param>
        /// <param name="AConstraint"></param>
        /// <param name="formalParametersKey"></param>
        /// <param name="actualParametersKey"></param>
        /// <param name="numberKeyColumns"></param>
        /// <param name="actualParametersToString"></param>
        private static void PrepareCodeletsKey(
            TTable ACurrentTable,
            TConstraint AConstraint,
            out string formalParametersKey,
            out string actualParametersKey,
            out string actualParametersToString,
            out int numberKeyColumns)
        {
            formalParametersKey      = "";
            actualParametersKey      = "";
            actualParametersToString = "";

            numberKeyColumns = AConstraint.strThisFields.Count;

            int counterKeyField = 0;

            foreach (string field in AConstraint.strThisFields)
            {
                if (counterKeyField > 0)
                {
                    formalParametersKey      += ", ";
                    actualParametersKey      += ", ";
                    actualParametersToString += " + \" \" + ";
                }

                TTableField typedField = ACurrentTable.GetField(field);

                formalParametersKey      += typedField.GetDotNetType() + " A" + TTable.NiceFieldName(field);
                actualParametersKey      += "A" + TTable.NiceFieldName(field);
                actualParametersToString += "A" + TTable.NiceFieldName(field) + ".ToString()";

                counterKeyField++;
            }

            // for partners, show their names as well. This is used in function AddOrModifyRecord to show the users which values are different
            foreach (TTableField column in ACurrentTable.grpTableField)
            {
                if (column.strName.Contains("_name_"))
                {
                    actualParametersToString += " + ExistingRecord[0]." + TTable.NiceFieldName(column) + ".ToString()";
                }
            }
        }
        /// <summary>write the code for the designer file where the properties of the control are written</summary>
        public override ProcessTemplate SetControlProperties(TFormWriter writer, TControlDef ctrl)
        {
            base.SetControlProperties(writer, ctrl);

            if (TYml2Xml.HasAttribute(ctrl.xmlNode, "SelectedRowActivates"))
            {
                // TODO: this function needs to be called by the manual code at the moment when eg a search finishes
                // TODO: call "Activate" + TYml2Xml.GetAttribute(ctrl.xmlNode, "SelectedRowActivates")
            }

            StringCollection Columns = TYml2Xml.GetElements(ctrl.xmlNode, "Columns");

            if (Columns.Count > 0)
            {
                writer.Template.AddToCodelet("INITMANUALCODE", ctrl.controlName + ".Columns.Clear();" + Environment.NewLine);

                foreach (string ColumnFieldName in Columns)
                {
                    bool        IsDetailNotMaster;
                    TTableField field = null;

                    // customfield, eg. UC_GLTransactions, ATransaction.DateEntered and ATransaction.AnalysisAttributes
                    // there needs to be a list of CustomColumns
                    XmlNode CustomColumnsNode = TYml2Xml.GetChild(ctrl.xmlNode, "CustomColumns");
                    XmlNode CustomColumnNode  = null;

                    if (CustomColumnsNode != null)
                    {
                        CustomColumnNode = TYml2Xml.GetChild(CustomColumnsNode, ColumnFieldName);
                    }

                    if (CustomColumnNode != null)
                    {
                        //string ColumnType = "System.String";

                        /* TODO DateTime (tracker: #58)
                         * if (TYml2Xml.GetAttribute(CustomColumnNode, "Type") == "System.DateTime")
                         * {
                         *  ColumnType = "DateTime";
                         * }
                         */

                        // TODO: different behaviour for double???
                        if (TYml2Xml.GetAttribute(CustomColumnNode, "Type") == "Boolean")
                        {
                            //ColumnType = "CheckBox";
                        }

                        writer.Template.AddToCodelet("INITMANUALCODE", ctrl.controlName + ".Columns.Add(" +
                                                     "FMainDS." + ctrl.GetAttribute("TableName") + ".Get" + ColumnFieldName + "DBName(), \"" +
                                                     TYml2Xml.GetAttribute(CustomColumnNode, "Label") + "\");" + Environment.NewLine);
                    }
                    else if (ctrl.HasAttribute("TableName"))
                    {
                        field =
                            TDataBinding.GetTableField(null, ctrl.GetAttribute("TableName") + "." + ColumnFieldName,
                                                       out IsDetailNotMaster,
                                                       true);
                    }
                    else
                    {
                        field = TDataBinding.GetTableField(null, ColumnFieldName, out IsDetailNotMaster, true);
                    }

                    if (field != null)
                    {
                        //string ColumnType = "System.String";

                        /* TODO DateTime (tracker: #58)
                         * if (field.GetDotNetType() == "System.DateTime")
                         * {
                         *  ColumnType = "DateTime";
                         * }
                         */

                        // TODO: different behaviour for double???
                        if (field.GetDotNetType() == "Boolean")
                        {
                            //ColumnType = "CheckBox";
                        }

                        writer.Template.AddToCodelet("INITMANUALCODE", ctrl.controlName + ".Columns.Add(" +
                                                     TTable.NiceTableName(field.strTableName) + "Table.Get" +
                                                     TTable.NiceFieldName(field.strName) + "DBName(), \"" +
                                                     field.strLabel + "\");" + Environment.NewLine);
                    }
                }
            }

            if (ctrl.HasAttribute("ActionLeavingRow"))
            {
                AssignEventHandlerToControl(writer, ctrl, "Selection.FocusRowLeaving", "SourceGrid.RowCancelEventHandler",
                                            ctrl.GetAttribute("ActionLeavingRow"));
            }

            if (ctrl.HasAttribute("ActionFocusRow"))
            {
// TODO                AssignEventHandlerToControl(writer, ctrl, "Selection.FocusRowEntered", "SourceGrid.RowEventHandler",
//                    ctrl.GetAttribute("ActionFocusRow"));
            }

            if ((ctrl.controlName == "grdDetails") && FCodeStorage.HasAttribute("DetailTable"))
            {
                writer.Template.AddToCodelet("SHOWDATA", "");

                if (ctrl.HasAttribute("SortOrder"))
                {
                    // SortOrder is comma separated and has DESC or ASC after the column name
                    string SortOrder = ctrl.GetAttribute("SortOrder");

                    foreach (string SortOrderPart in SortOrder.Split(','))
                    {
                        bool        temp;
                        TTableField field = null;

                        if ((SortOrderPart.Split(' ')[0].IndexOf(".") == -1) && ctrl.HasAttribute("TableName"))
                        {
                            field =
                                TDataBinding.GetTableField(null, ctrl.GetAttribute("TableName") + "." + SortOrderPart.Split(
                                                               ' ')[0], out temp, true);
                        }
                        else
                        {
                            field =
                                TDataBinding.GetTableField(
                                    null,
                                    SortOrderPart.Split(' ')[0],
                                    out temp, true);
                        }

                        if (field != null)
                        {
                            SortOrder = SortOrder.Replace(SortOrderPart.Split(' ')[0], field.strName);
                        }
                    }

                    writer.Template.AddToCodelet("GRIDSORT", SortOrder);
                }

                if (ctrl.HasAttribute("RowFilter"))
                {
                    // this references a field in the table, and assumes there exists a local variable with the same name
                    // eg. FBatchNumber in GL Journals
                    string RowFilter = ctrl.GetAttribute("RowFilter");

                    String FilterString = "\"";

                    foreach (string RowFilterPart in RowFilter.Split(','))
                    {
                        bool   temp;
                        string columnName =
                            TDataBinding.GetTableField(
                                null,
                                RowFilterPart,
                                out temp, true).strName;

                        if (FilterString.Length > 1)
                        {
                            FilterString += " + \" and ";
                        }

                        FilterString += columnName + " = \" + F" + TTable.NiceFieldName(columnName) + ".ToString()";
                    }

                    writer.Template.AddToCodelet("GRIDFILTER", FilterString);
                }
            }

            return(writer.FTemplate);
        }
        /// <summary>write the code for the designer file where the properties of the control are written</summary>
        public override ProcessTemplate SetControlProperties(TFormWriter writer, TControlDef ctrl)
        {
            if (!ctrl.HasAttribute("Width"))
            {
                ctrl.SetAttribute("Width", FDefaultWidth.ToString());
            }

            base.SetControlProperties(writer, ctrl);

            writer.Template.AddToCodelet("INITMANUALCODE", ctrl.controlName + ".CancelEditingWithEscapeKey = false;" + Environment.NewLine);

            if (TYml2Xml.HasAttribute(ctrl.xmlNode, "SelectedRowActivates"))
            {
                // TODO: this function needs to be called by the manual code at the moment when eg a search finishes
                // TODO: call "Activate" + TYml2Xml.GetAttribute(ctrl.xmlNode, "SelectedRowActivates")
            }

            StringCollection Columns = TYml2Xml.GetElements(ctrl.xmlNode, "Columns");

            if (Columns.Count > 0)
            {
                writer.Template.AddToCodelet("INITMANUALCODE", ctrl.controlName + ".Columns.Clear();" + Environment.NewLine);

                //This needs to come immediately after the Columns.Clear() and before the creation of the columns
                if (ctrl.HasAttribute("SortableHeaders"))
                {
                    string trueOrFalse = ctrl.GetAttribute("SortableHeaders");
                    writer.Template.AddToCodelet("INITMANUALCODE", ctrl.controlName + ".SortableHeaders = " + trueOrFalse + ";" + Environment.NewLine);
                }

                bool isFirstColumnVarchar = false;
                bool doneFirstColumn      = false;

                foreach (string ColumnFieldName in Columns)
                {
                    bool        IsDetailNotMaster;
                    TTableField field = null;
                    string      TableFieldTable;
                    string      ColumnFieldNameResolved;

                    // customfield, eg. UC_GLTransactions, ATransaction.DateEntered and ATransaction.AnalysisAttributes
                    // there needs to be a list of CustomColumns
                    XmlNode CustomColumnsNode = TYml2Xml.GetChild(ctrl.xmlNode, "CustomColumns");
                    XmlNode CustomColumnNode  = null;

                    if (CustomColumnsNode != null)
                    {
                        CustomColumnNode = TYml2Xml.GetChild(CustomColumnsNode, ColumnFieldName);
                    }

                    if ((ctrl.controlName == "grdDetails") && FCodeStorage.HasAttribute("DetailTable"))
                    {
                        TableFieldTable = FCodeStorage.GetAttribute("DetailTable");

                        if (ColumnFieldName.StartsWith("Detail") && !IsLegitimateDetailFieldName(TableFieldTable, ColumnFieldName))
                        {
                            ColumnFieldNameResolved = ColumnFieldName.Substring(6);     // Drop 'Details' out of 'Details...'
                        }
                        else
                        {
                            ColumnFieldNameResolved = ColumnFieldName;
                        }
                    }
                    else
                    {
                        TableFieldTable         = ctrl.GetAttribute("TableName");
                        ColumnFieldNameResolved = ColumnFieldName;
                    }

                    if (CustomColumnNode != null)
                    {
                        TTableField tf = null;

                        // if grd has no TableName property
                        if ((TableFieldTable == "") && ColumnFieldNameResolved.Contains("."))
                        {
                            int    Period     = ColumnFieldNameResolved.IndexOf(".");
                            string TableName  = ColumnFieldNameResolved.Remove(Period);
                            string ColumnName = ColumnFieldNameResolved.Remove(0, TableName.Length + 1);

                            AddColumnToGrid(writer, ctrl.controlName,
                                            TYml2Xml.GetAttribute(CustomColumnNode, "Type"),
                                            TYml2Xml.GetAttribute(CustomColumnNode, "Label"),
                                            TYml2Xml.GetAttribute(CustomColumnNode, "Tooltip"),
                                            TableName,
                                            ColumnName);
                            tf = TDataBinding.GetTableField(null, TableName + "." + ColumnName, out IsDetailNotMaster, true);
                        }
                        else
                        {
                            AddColumnToGrid(writer, ctrl.controlName,
                                            TYml2Xml.GetAttribute(CustomColumnNode, "Type"),
                                            TYml2Xml.GetAttribute(CustomColumnNode, "Label"),
                                            TYml2Xml.GetAttribute(CustomColumnNode, "Tooltip"),
                                            TableFieldTable,
                                            ColumnFieldNameResolved);
                            tf = TDataBinding.GetTableField(null, TableFieldTable + "." + ColumnFieldNameResolved, out IsDetailNotMaster, true);
                        }

                        if (!doneFirstColumn)
                        {
                            isFirstColumnVarchar = tf.strName.EndsWith("_c");
                            doneFirstColumn      = true;
                        }
                    }
                    else if (ctrl.HasAttribute("TableName"))
                    {
                        field = TDataBinding.GetTableField(null, ctrl.GetAttribute("TableName") + "." + ColumnFieldName,
                                                           out IsDetailNotMaster, true);
                    }
                    else
                    {
                        field = TDataBinding.GetTableField(null, ColumnFieldName, out IsDetailNotMaster, true);
                    }

                    if (field != null)
                    {
                        AddColumnToGrid(writer, ctrl.controlName,
                                        field.iDecimals == 10 && field.iLength == 24 ? "Decimal" : field.GetDotNetType(),
                                        field.strLabel.Length > 0 ? field.strLabel : field.strName,
                                        String.Empty,
                                        TTable.NiceTableName(field.strTableName),
                                        TTable.NiceFieldName(field.strName));

                        if (!doneFirstColumn)
                        {
                            isFirstColumnVarchar = field.strName.EndsWith("_c");
                            doneFirstColumn      = true;
                        }
                    }
                }

                if (FControlType == TYPE_DATA_GRID_NON_PAGED)
                {
                    // Grid AutoFind definition (not allowed in paged grids)
                    string autoFindStr = ctrl.controlName + ".AutoFindMode = TAutoFindModeEnum.";
                    string mode        = "NoAutoFind";

                    if (ctrl.HasAttribute("AutoFindMode"))
                    {
                        // Use the specified value in YAML
                        mode = ctrl.GetAttribute("AutoFindMode");
                        TLogging.Log("Info: AutoFindMode (with columns) was set to " + mode + " from explicit YAML attribute: " + ctrl.controlName);
                    }
                    else if (isFirstColumnVarchar)
                    {
                        // We can use auto-find because we have a first column based on a varchar
                        mode = "FirstCharacter";
                        TLogging.Log("Info: AutoFindMode (with columns) was set implicitly for: " + ctrl.controlName);
                    }
                    else
                    {
                        TLogging.Log("Info: AutoFindMode (with columns) was set to NoAutoFind for: " + ctrl.controlName);
                    }

                    writer.Template.AddToCodelet("INITMANUALCODE", autoFindStr + mode + ";" + Environment.NewLine);

                    if (ctrl.HasAttribute("AutoFindColumn"))
                    {
                        string colNum = ctrl.GetAttribute("AutoFindColumn");
                        writer.Template.AddToCodelet("INITMANUALCODE",
                                                     ctrl.controlName + ".AutoFindColumn = " + colNum + ";" + Environment.NewLine);
                        TLogging.Log("Info: AutoFindColumn was set to " + colNum + " for: " + ctrl.controlName);
                    }

                    if ((mode == "FirstCharacter") && !ctrl.HasAttribute("SortOrder"))
                    {
                        TLogging.Log("Info: AutoFind has been turned on for a grid with no YAML-defined sort order: (" + ctrl.controlName +
                                     "). You can remove this message by explicitly setting a SortOrder in the YAML file.");
                    }
                }
            }
            else
            {
                //If no columns, but the user is able to add columns dynamically during the running of the form, then need this here.
                if (ctrl.HasAttribute("SortableHeaders"))
                {
                    string trueOrFalse = ctrl.GetAttribute("SortableHeaders");
                    writer.Template.AddToCodelet("INITMANUALCODE", ctrl.controlName + ".SortableHeaders = " + trueOrFalse + ";" + Environment.NewLine);
                }

                if (FControlType == TYPE_DATA_GRID_NON_PAGED)
                {
                    // Grid AutoFind definition (not allowed in paged grids)
                    string autoFindStr = ctrl.controlName + ".AutoFindMode = TAutoFindModeEnum.";
                    string mode        = "FirstCharacter";

                    if (ctrl.HasAttribute("AutoFindMode"))
                    {
                        // Use the specified value in YAML
                        mode = ctrl.GetAttribute("AutoFindMode");
                        TLogging.Log("Info: AutoFindMode (without columns) was set to " + mode + " from explicit YAML attribute: " + ctrl.controlName);
                    }
                    else if (writer.FCodeStorage.ManualFileExistsAndContains(ctrl.controlName + ".AddTextColumn("))
                    {
                        // We presume can use auto-find because we have a column (maybe the first) based on a varchar
                        TLogging.Log("Info: AutoFindMode (without columns) was set implicitly for: " + ctrl.controlName);
                    }
                    else
                    {
                        mode = "NoAutoFind";
                        TLogging.Log("Info: AutoFindMode (without columns) was set to NoAutoFind for: " + ctrl.controlName);
                    }

                    writer.Template.AddToCodelet("INITMANUALCODE", autoFindStr + mode + ";" + Environment.NewLine);

                    if (ctrl.HasAttribute("AutoFindColumn"))
                    {
                        string colNum = ctrl.GetAttribute("AutoFindColumn");
                        writer.Template.AddToCodelet("INITMANUALCODE",
                                                     ctrl.controlName + ".AutoFindColumn = " + colNum + ";" + Environment.NewLine);
                        TLogging.Log("Info: AutoFindColumn was set to " + colNum + " for: " + ctrl.controlName);
                    }
                }
            }

            if (ctrl.controlName != "grdDetails")
            {
                if (ctrl.HasAttribute("ActionLeavingRow"))
                {
                    AssignEventHandlerToControl(writer, ctrl, "Selection.FocusRowLeaving", "SourceGrid.RowCancelEventHandler",
                                                ctrl.GetAttribute("ActionLeavingRow"));
                }

                if (ctrl.HasAttribute("ActionFocusRow"))
                {
                    AssignEventHandlerToControl(writer, ctrl, "Selection.FocusRowEntered", "SourceGrid.RowEventHandler",
                                                ctrl.GetAttribute("ActionFocusRow"));
                }
            }

            if (ctrl.HasAttribute("ActionEnterKeyPressed"))
            {
                AssignEventHandlerToControl(writer, ctrl, "EnterKeyPressed", "TKeyPressedEventHandler",
                                            ctrl.GetAttribute("ActionEnterKeyPressed"));
            }

            if ((ctrl.controlName == "grdDetails") && FCodeStorage.HasAttribute("DetailTable"))
            {
                writer.Template.AddToCodelet("SHOWDATA", "");

                if (ctrl.HasAttribute("SortOrder"))
                {
                    // SortOrder is comma separated and has DESC or ASC after the column name
                    string SortOrder = ctrl.GetAttribute("SortOrder");

                    foreach (string SortOrderPart in SortOrder.Split(','))
                    {
                        bool        temp;
                        TTableField field          = null;
                        string      columnNamePart = SortOrderPart.Split(' ')[0];

                        if ((columnNamePart.IndexOf(".") == -1) && ctrl.HasAttribute("TableName"))
                        {
                            field = TDataBinding.GetTableField(null, ctrl.GetAttribute("TableName") + "." + columnNamePart, out temp, true);
                        }
                        else
                        {
                            field = TDataBinding.GetTableField(null, columnNamePart, out temp, true);
                        }

                        if (field != null)
                        {
                            SortOrder = SortOrder.Replace(columnNamePart, field.strName);
                        }
                    }

                    writer.Template.AddToCodelet("GRIDSORT", SortOrder);
                }

                if (ctrl.HasAttribute("RowFilter"))
                {
                    // this references a field in the table, and assumes there exists a local variable with the same name
                    // eg. FBatchNumber in GL Journals
                    string RowFilter = ctrl.GetAttribute("RowFilter");

                    String FilterString = "\"";

                    foreach (string RowFilterPart in RowFilter.Split(','))
                    {
                        bool   temp;
                        string columnName =
                            TDataBinding.GetTableField(
                                null,
                                RowFilterPart,
                                out temp, true).strName;

                        if (FilterString.Length > 1)
                        {
                            FilterString += " + \" and ";
                        }

                        FilterString += columnName + " = \" + F" + TTable.NiceFieldName(columnName) + ".ToString()";
                    }

                    writer.Template.AddToCodelet("GRIDFILTER", FilterString);
                }
            }

            if (ctrl.controlName == "grdDetails")
            {
                if (ctrl.HasAttribute("EnableMultiSelection"))
                {
                    writer.Template.SetCodelet("GRIDMULTISELECTION",
                                               String.Format("grdDetails.Selection.EnableMultiSelection = {0};{1}", ctrl.GetAttribute("EnableMultiSelection"),
                                                             Environment.NewLine));
                }
                else if (FCodeStorage.FControlList.ContainsKey("btnDelete"))
                {
                    writer.Template.SetCodelet("GRIDMULTISELECTION",
                                               "grdDetails.Selection.EnableMultiSelection = true;" + Environment.NewLine);
                }
            }

            return(writer.FTemplate);
        }
        /// <summary>
        /// Generates code for the UNDODATA Snippet.
        /// </summary>
        /// <param name="tablename">Name of table</param>
        /// <param name="fieldname">Name of field</param>
        /// <param name="TestForNullTable"></param>
        /// <param name="writer">FormWriter instance.</param>
        /// <param name="ctrl">TControlDef instance.</param>
        /// <param name="AField">TTableField instance.</param>
        /// <returns>A <see cref="ProcessTemplate"></see>.</returns>
        ProcessTemplate GenerateUndoDataSnippetCode(ref string tablename,
            ref string fieldname,
            ref string TestForNullTable,
            TFormWriter writer,
            TControlDef ctrl,
            TTableField AField)
        {
            ProcessTemplate snippetShowData = writer.Template.GetSnippet("UNDODATAFORCOLUMN");

            snippetShowData.SetCodelet("NOTDEFAULTTABLE", TestForNullTable);

            snippetShowData.SetCodelet("UNDOCONTROLVALUE",
                this.UndoValue(ctrl, "ARow[FMainDS." + tablename + ".Columns[(short)FMainDS." + tablename + ".GetType().GetField(\"Column" +
                    fieldname +
                    "Id\", BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy).GetValue(FMainDS." + tablename +
                    ".GetType())], DataRowVersion.Original]",
                    AField.GetDotNetType()));
            snippetShowData.InsertSnippet("UNDOROWVALUE", writer.Template.GetSnippet("UNDOROWVALUE"));

            snippetShowData.SetCodelet("CONTROLNAME", ctrl.controlName);

            return snippetShowData;
        }
        /// <summary>
        /// Generates code for the SHOWDATA Snippet.
        /// </summary>
        /// <param name="fieldname">Name of field</param>
        /// <param name="RowName">Name of row</param>
        /// <param name="TestForNullTable"></param>
        /// <param name="writer">FormWriter instance.</param>
        /// <param name="ctrl">TControlDef instance.</param>
        /// <param name="AField">TTableField instance.</param>
        /// <returns>A <see cref="ProcessTemplate"></see>.</returns>
        ProcessTemplate GenerateShowDataSnippetCode(ref string fieldname,
            ref string RowName,
            ref string TestForNullTable,
            TFormWriter writer,
            TControlDef ctrl,
            TTableField AField)
        {
            ProcessTemplate snippetShowData = writer.Template.GetSnippet("SHOWDATAFORCOLUMN");

            if (AField.GetDotNetType().ToLower().Contains("string"))
            {
                snippetShowData.SetCodelet("SETVALUEORNULL", "{#SETCONTROLVALUE}");
                snippetShowData.SetCodelet("SETROWVALUEORNULL", "{#SETROWVALUE}");
            }
            else
            {
                snippetShowData.InsertSnippet("SETVALUEORNULL", writer.Template.GetSnippet("SETVALUEORNULL"));
                snippetShowData.InsertSnippet("SETROWVALUEORNULL", writer.Template.GetSnippet("SETROWVALUEORNULL"));
            }

            snippetShowData.SetCodelet("CANBENULL", !AField.bNotNull ? "yes" : "");
            snippetShowData.SetCodelet("DETERMINECONTROLISNULL", this.GetControlValue(ctrl, null));
            snippetShowData.SetCodelet("NOTDEFAULTTABLE", TestForNullTable);
            snippetShowData.SetCodelet("ROW", RowName);
            snippetShowData.SetCodelet("COLUMNNAME", fieldname);
            snippetShowData.SetCodelet("SETNULLVALUE", this.AssignValue(ctrl, null, null));
            snippetShowData.SetCodelet("SETCONTROLVALUE", this.AssignValue(ctrl, RowName + "." + fieldname, AField.GetDotNetType()));
            snippetShowData.InsertSnippet("SETROWVALUE", writer.Template.GetSnippet("SETROWVALUE"));

            return snippetShowData;
        }
        private void LinkControlDataField(TFormWriter writer, TControlDef ctrl, TTableField AField, bool AIsDetailNotMaster)
        {
            ProcessTemplate snippetValidationControlsDictAdd;
            bool AutomDataValidation;
            string ReasonForAutomValidation;
            string ColumnIDStr;
            bool OKToGenerateDVCode = true;

            if (AField == null)
            {
                return;
            }

            string tablename = TTable.NiceTableName(AField.strTableName);
            string fieldname = TTable.NiceFieldName(AField);
            string RowName = "FMainDS." + tablename + "[0]";
            string TestForNullTable = "FMainDS." + tablename;

            if ((tablename == writer.CodeStorage.GetAttribute("DetailTable")) || (tablename == writer.CodeStorage.GetAttribute("MasterTable")))
            {
                RowName = "ARow";
                TestForNullTable = "";
            }

            string targetCodelet = "SHOWDATA";

            if (tablename == writer.CodeStorage.GetAttribute("DetailTable"))
            {
                targetCodelet = "SHOWDETAILS";
            }

            ProcessTemplate snippetShowData = GenerateShowDataSnippetCode(ref fieldname, ref RowName, ref TestForNullTable, writer, ctrl, AField);

            writer.Template.InsertSnippet(targetCodelet, snippetShowData);

            if (AField.bPartOfPrimKey)
            {
                // check if the current row is new; then allow changing the primary key; otherwise make the control readonly
                writer.Template.AddToCodelet(targetCodelet, ctrl.controlName + "." + (FHasReadOnlyProperty ? "ReadOnly" : "Enabled") + " = " +
                    "(" + RowName + ".RowState " + (FHasReadOnlyProperty ? "!=" : "==") + " DataRowState.Added);" + Environment.NewLine);
                writer.Template.AddToCodelet("PRIMARYKEYCONTROLSREADONLY",
                    ctrl.controlName + "." + (FHasReadOnlyProperty ? "ReadOnly = " : "Enabled = !") + "AReadOnly;" + Environment.NewLine);
            }

            if (ctrl.GetAttribute("ReadOnly").ToLower() != "true")
            {
                targetCodelet = targetCodelet.Replace("SHOW", "SAVE");

                ProcessTemplate snippetGetData = writer.Template.GetSnippet("GETDATAFORCOLUMNTHATCANBENULL");

                if (AField.GetDotNetType().ToLower().Contains("string"))
                {
                    snippetGetData.SetCodelet("GETVALUEORNULL", "{#ROW}.{#COLUMNNAME} = {#CONTROLVALUE};");
                    snippetGetData.InsertSnippet("GETROWVALUEORNULL", writer.Template.GetSnippet("GETROWVALUEORNULLSTRING"));
                }
                else
                {
                    snippetGetData.InsertSnippet("GETVALUEORNULL", writer.Template.GetSnippet("GETVALUEORNULL"));
                    snippetGetData.InsertSnippet("GETROWVALUEORNULL", writer.Template.GetSnippet("GETROWVALUEORNULL"));
                }

                snippetGetData.SetCodelet("CANBENULL", !AField.bNotNull && (this.GetControlValue(ctrl, null) != null) ? "yes" : "");
                snippetGetData.SetCodelet("NOTDEFAULTTABLE", TestForNullTable);
                snippetGetData.SetCodelet("DETERMINECONTROLISNULL", this.GetControlValue(ctrl, null));
                snippetGetData.SetCodelet("ROW", RowName);
                snippetGetData.SetCodelet("COLUMNNAME", fieldname);
                snippetGetData.SetCodelet("CONTROLVALUE", this.GetControlValue(ctrl, AField.GetDotNetType()));
                snippetGetData.SetCodelet("CONTROLNAME", ctrl.controlName);

                writer.Template.InsertSnippet(targetCodelet, snippetGetData);
            }

            // setstatusbar tooltips for datafields, with getstring plus value from petra.xml
            string helpText = AField.strHelp;

            if (helpText.Length == 0)
            {
                helpText = AField.strDescription;
            }

            if ((helpText.Length > 0) && (ctrl.GetAttribute("Tooltip").Length == 0))
            {
                writer.Template.AddToCodelet("INITUSERCONTROLS", "FPetraUtilsObject.SetStatusBarText(" + ctrl.controlName +
                    ", Catalog.GetString(\"" +
                    helpText.Replace("\"", "\\\"") +                           // properly escape double quotation marks
                    "\"));" + Environment.NewLine);
            }

            // Data Validation
            if (GenerateDataValidationCode(writer, ctrl, out AutomDataValidation, out ReasonForAutomValidation))
            {
                string targetCodeletValidation = "ADDCONTROLTOVALIDATIONCONTROLSDICT";

                ColumnIDStr = "FMainDS." + tablename + ".Columns[(short)FMainDS." + tablename + ".GetType().GetField(\"Column" + fieldname +
                              "Id\", BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy).GetValue(FMainDS." + tablename +
                              ".GetType())]";

                if (writer.Template.FCodelets.Keys.Contains(targetCodeletValidation))
                {
                    // Check if code for the addition of a certain DataColumn is is already contained in Template;
                    // if so, skip a further addition to prevent an Exception at runtime
                    if (writer.Template.FCodelets[targetCodeletValidation].ToString().Contains(ColumnIDStr))
                    {
                        OKToGenerateDVCode = false;
                    }
                }

                if (OKToGenerateDVCode)
                {
                    if (!ctrl.GetAttribute("Validation").ToLower().StartsWith("pair("))
                    {
                        snippetValidationControlsDictAdd = writer.Template.GetSnippet("VALIDATIONCONTROLSDICTADD");
                    }
                    else
                    {
                        snippetValidationControlsDictAdd = writer.Template.GetSnippet("VALIDATIONCONTROLSDICTADDMULTI");

                        string PairControlName = ctrl.GetAttribute("Validation").Substring(5, ctrl.GetAttribute("Validation").Length - 6);
                        TControlDef SecondValidationControl = writer.CodeStorage.GetControl(PairControlName);

                        if (SecondValidationControl != null)
                        {
                            snippetValidationControlsDictAdd.SetCodelet("VALIDATIONCONTROL2", SecondValidationControl.controlName);

                            if (TFormWriter.ProperI18NCatalogGetString(StringHelper.TrimQuotes(SecondValidationControl.Label)))
                            {
                                snippetValidationControlsDictAdd.SetCodelet("LABELTEXT2",
                                    "Catalog.GetString(" + "\"" + SecondValidationControl.Label + "\")");
                            }
                            else
                            {
                                snippetValidationControlsDictAdd.SetCodelet("LABELTEXT2", "\"" + SecondValidationControl.Label + "\"");
                            }
                        }
                        else
                        {
                            throw new ApplicationException(
                                "Pair Control for Validation '" + PairControlName + "' does not exist. Please specify a valid control!");
                        }
                    }

                    snippetValidationControlsDictAdd.SetCodelet("TABLENAME", tablename);
                    snippetValidationControlsDictAdd.SetCodelet("COLUMNID", ColumnIDStr);
                    snippetValidationControlsDictAdd.SetCodelet("VALIDATIONCONTROLSDICTVAR",
                        writer.Template.FTemplateCode.Contains(
                            "FValidationControlsDict") ? "FValidationControlsDict" : "FPetraUtilsObject.ValidationControlsDict");

                    if (AutomDataValidation)
                    {
                        snippetValidationControlsDictAdd.SetCodelet("AUTOMATICVALIDATIONCOMMENT",
                            " // Automatic Data Validation based on DB specification: " + ReasonForAutomValidation);
                    }
                    else
                    {
                        snippetValidationControlsDictAdd.SetCodelet("AUTOMATICVALIDATIONCOMMENT", "");
                    }

                    snippetValidationControlsDictAdd.SetCodelet("VALIDATIONCONTROL", ctrl.controlName);

                    if (TFormWriter.ProperI18NCatalogGetString(StringHelper.TrimQuotes(ctrl.Label)))
                    {
                        snippetValidationControlsDictAdd.SetCodelet("LABELTEXT", "Catalog.GetString(" + "\"" + ctrl.Label + "\")");
                    }
                    else
                    {
                        snippetValidationControlsDictAdd.SetCodelet("LABELTEXT", "\"" + ctrl.Label + "\"");
                    }

                    writer.Template.InsertSnippet(targetCodeletValidation, snippetValidationControlsDictAdd);
                }
            }
        }
Exemple #8
0
 /// <summary>
 /// convert an sql type from our xml file into a dotnet type.
 /// should also work for Convert.To&lt;DotNetType&gt;
 /// </summary>
 /// <param name="tableField"></param>
 /// <returns></returns>
 public static string ToDotNetType(TTableField tableField)
 {
     return(tableField.GetDotNetType());
 }
 /// <summary>
 /// convert an sql type from our xml file into a dotnet type.
 /// should also work for Convert.To&lt;DotNetType&gt;
 /// </summary>
 /// <param name="tableField"></param>
 /// <returns></returns>
 public static string ToDotNetType(TTableField tableField)
 {
     return tableField.GetDotNetType();
 }
Exemple #10
0
        /// <summary>write the code for the designer file where the properties of the control are written</summary>
        public override ProcessTemplate SetControlProperties(TFormWriter writer, TControlDef ctrl)
        {
            if (!ctrl.HasAttribute("Width"))
            {
                ctrl.SetAttribute("Width", FDefaultWidth.ToString());
            }

            base.SetControlProperties(writer, ctrl);

            writer.Template.AddToCodelet("INITMANUALCODE", ctrl.controlName + ".CancelEditingWithEscapeKey = false;" + Environment.NewLine);

            if (TYml2Xml.HasAttribute(ctrl.xmlNode, "SelectedRowActivates"))
            {
                // TODO: this function needs to be called by the manual code at the moment when eg a search finishes
                // TODO: call "Activate" + TYml2Xml.GetAttribute(ctrl.xmlNode, "SelectedRowActivates")
            }

            StringCollection Columns = TYml2Xml.GetElements(ctrl.xmlNode, "Columns");

            if (Columns.Count > 0)
            {
                writer.Template.AddToCodelet("INITMANUALCODE", ctrl.controlName + ".Columns.Clear();" + Environment.NewLine);

                //This needs to come immediately after the Columns.Clear() and before the creation of the columns
                if (ctrl.HasAttribute("SortableHeaders"))
                {
                    string trueOrFalse = ctrl.GetAttribute("SortableHeaders");
                    writer.Template.AddToCodelet("INITMANUALCODE", ctrl.controlName + ".SortableHeaders = " + trueOrFalse + ";" + Environment.NewLine);
                }

                foreach (string ColumnFieldName in Columns)
                {
                    bool        IsDetailNotMaster;
                    TTableField field = null;
                    string      TableFieldTable;
                    string      ColumnFieldNameResolved;

                    // customfield, eg. UC_GLTransactions, ATransaction.DateEntered and ATransaction.AnalysisAttributes
                    // there needs to be a list of CustomColumns
                    XmlNode CustomColumnsNode = TYml2Xml.GetChild(ctrl.xmlNode, "CustomColumns");
                    XmlNode CustomColumnNode  = null;

                    if (CustomColumnsNode != null)
                    {
                        CustomColumnNode = TYml2Xml.GetChild(CustomColumnsNode, ColumnFieldName);
                    }

                    if ((ctrl.controlName == "grdDetails") && FCodeStorage.HasAttribute("DetailTable"))
                    {
                        TableFieldTable = FCodeStorage.GetAttribute("DetailTable");

                        if (ColumnFieldName.StartsWith("Detail") && !IsLegitimateDetailFieldName(TableFieldTable, ColumnFieldName))
                        {
                            ColumnFieldNameResolved = ColumnFieldName.Substring(6);     // Drop 'Details' out of 'Details...'
                        }
                        else
                        {
                            ColumnFieldNameResolved = ColumnFieldName;
                        }
                    }
                    else
                    {
                        TableFieldTable         = ctrl.GetAttribute("TableName");
                        ColumnFieldNameResolved = ColumnFieldName;
                    }

                    if (CustomColumnNode != null)
                    {
                        // if grd has no TableName property
                        if ((TableFieldTable == "") && ColumnFieldNameResolved.Contains("."))
                        {
                            int    Period     = ColumnFieldNameResolved.IndexOf(".");
                            string TableName  = ColumnFieldNameResolved.Remove(Period);
                            string ColumnName = ColumnFieldNameResolved.Remove(0, TableName.Length + 1);

                            AddColumnToGrid(writer, ctrl.controlName,
                                            TYml2Xml.GetAttribute(CustomColumnNode, "Type"),
                                            TYml2Xml.GetAttribute(CustomColumnNode, "Label"),
                                            TYml2Xml.GetAttribute(CustomColumnNode, "Tooltip"),
                                            TableName,
                                            ColumnName);
                        }
                        else
                        {
                            AddColumnToGrid(writer, ctrl.controlName,
                                            TYml2Xml.GetAttribute(CustomColumnNode, "Type"),
                                            TYml2Xml.GetAttribute(CustomColumnNode, "Label"),
                                            TYml2Xml.GetAttribute(CustomColumnNode, "Tooltip"),
                                            TableFieldTable,
                                            ColumnFieldNameResolved);
                        }
                    }
                    else if (ctrl.HasAttribute("TableName"))
                    {
                        field =
                            TDataBinding.GetTableField(null, ctrl.GetAttribute("TableName") + "." + ColumnFieldName, out IsDetailNotMaster,
                                                       true);
                    }
                    else
                    {
                        field = TDataBinding.GetTableField(null, ColumnFieldName, out IsDetailNotMaster, true);
                    }

                    if (field != null)
                    {
                        AddColumnToGrid(writer, ctrl.controlName,
                                        field.iDecimals == 10 && field.iLength == 24 ? "Decimal" : field.GetDotNetType(),
                                        field.strLabel.Length > 0 ? field.strLabel : field.strName,
                                        String.Empty,
                                        TTable.NiceTableName(field.strTableName),
                                        TTable.NiceFieldName(field.strName));
                    }
                }
            }
            else
            {
                //If no columns, but the user is able to add columns dynamically during the running of the form, then need this here.
                if (ctrl.HasAttribute("SortableHeaders"))
                {
                    string trueOrFalse = ctrl.GetAttribute("SortableHeaders");
                    writer.Template.AddToCodelet("INITMANUALCODE", ctrl.controlName + ".SortableHeaders = " + trueOrFalse + ";" + Environment.NewLine);
                }
            }

            if (ctrl.controlName != "grdDetails")
            {
                if (ctrl.HasAttribute("ActionLeavingRow"))
                {
                    AssignEventHandlerToControl(writer, ctrl, "Selection.FocusRowLeaving", "SourceGrid.RowCancelEventHandler",
                                                ctrl.GetAttribute("ActionLeavingRow"));
                }

                if (ctrl.HasAttribute("ActionFocusRow"))
                {
                    AssignEventHandlerToControl(writer, ctrl, "Selection.FocusRowEntered", "SourceGrid.RowEventHandler",
                                                ctrl.GetAttribute("ActionFocusRow"));
                }
            }

            if (ctrl.HasAttribute("ActionEnterKeyPressed"))
            {
                AssignEventHandlerToControl(writer, ctrl, "EnterKeyPressed", "TKeyPressedEventHandler",
                                            ctrl.GetAttribute("ActionEnterKeyPressed"));
            }

            if ((ctrl.controlName == "grdDetails") && FCodeStorage.HasAttribute("DetailTable"))
            {
                writer.Template.AddToCodelet("SHOWDATA", "");

                if (ctrl.HasAttribute("SortOrder"))
                {
                    // SortOrder is comma separated and has DESC or ASC after the column name
                    string SortOrder = ctrl.GetAttribute("SortOrder");

                    foreach (string SortOrderPart in SortOrder.Split(','))
                    {
                        bool        temp;
                        TTableField field = null;

                        if ((SortOrderPart.Split(' ')[0].IndexOf(".") == -1) && ctrl.HasAttribute("TableName"))
                        {
                            field = TDataBinding.GetTableField(null, ctrl.GetAttribute("TableName") + "." + SortOrderPart.Split(
                                                                   ' ')[0], out temp, true);
                        }
                        else
                        {
                            field =
                                TDataBinding.GetTableField(
                                    null,
                                    SortOrderPart.Split(' ')[0],
                                    out temp, true);
                        }

                        if (field != null)
                        {
                            SortOrder = SortOrder.Replace(SortOrderPart.Split(' ')[0], field.strName);
                        }
                    }

                    writer.Template.AddToCodelet("GRIDSORT", SortOrder);
                }

                if (ctrl.HasAttribute("RowFilter"))
                {
                    // this references a field in the table, and assumes there exists a local variable with the same name
                    // eg. FBatchNumber in GL Journals
                    string RowFilter = ctrl.GetAttribute("RowFilter");

                    String FilterString = "\"";

                    foreach (string RowFilterPart in RowFilter.Split(','))
                    {
                        bool   temp;
                        string columnName =
                            TDataBinding.GetTableField(
                                null,
                                RowFilterPart,
                                out temp, true).strName;

                        if (FilterString.Length > 1)
                        {
                            FilterString += " + \" and ";
                        }

                        FilterString += columnName + " = \" + F" + TTable.NiceFieldName(columnName) + ".ToString()";
                    }

                    writer.Template.AddToCodelet("GRIDFILTER", FilterString);
                }
            }

            if (ctrl.controlName == "grdDetails")
            {
                if (ctrl.HasAttribute("EnableMultiSelection"))
                {
                    writer.Template.SetCodelet("GRIDMULTISELECTION",
                                               String.Format("grdDetails.Selection.EnableMultiSelection = {0};{1}", ctrl.GetAttribute("EnableMultiSelection"),
                                                             Environment.NewLine));
                }
                else if (FCodeStorage.FControlList.ContainsKey("btnDelete"))
                {
                    writer.Template.SetCodelet("GRIDMULTISELECTION",
                                               "grdDetails.Selection.EnableMultiSelection = true;" + Environment.NewLine);
                }
            }

            return(writer.FTemplate);
        }