private void AppendSubGridButtons(string fieldName, string recordType, List <Action <RecordEntryViewModelBase> > methods)
        {
            var fieldMetadata = ObjectRecordService.GetFieldMetadata(fieldName, recordType);

            if (fieldMetadata.FieldType == RecordFieldType.Enumerable)
            {
                methods.Add(
                    re => re.StartNewAction(() =>
                {
                    if (re is RecordEntryFormViewModel)
                    {
                        var refvm           = re as RecordEntryFormViewModel;
                        var customFunctions = GetCustomFunctionsFor(fieldName, refvm).ToList();
                        var fieldVm         = refvm.GetEnumerableFieldViewModel(fieldName);
                        fieldVm.DynamicGridViewModel.AddGridButtons(customFunctions);
                    }
                }));
            }
        }
        internal override RecordEntryFormViewModel GetLoadRowViewModel(string subGridName, RecordEntryViewModelBase parentForm, Action <IRecord> onSave, Action onCancel)
        {
            var propertyInfo = ObjectToEnter.GetType().GetProperty(subGridName);

            if (propertyInfo.GetCustomAttribute <FormEntry>() != null)
            {
                //lets start a dialog to add it on complete
                var fieldMetadata = (EnumerableFieldMetadata)ObjectRecordService.GetFieldMetadata(propertyInfo.Name, ObjectToEnter.GetType().AssemblyQualifiedName);
                var newRecord     = (ObjectRecord)ObjectRecordService.NewRecord(fieldMetadata.EnumeratedTypeQualifiedName);
                var newObject     = newRecord.Instance;
                var recordService = new ObjectRecordService(newObject, ObjectRecordService.LookupService, ObjectRecordService.OptionSetLimitedValues, ObjectRecordService, subGridName, parentForm.ApplicationController);
                var viewModel     = new ObjectEntryViewModel(
                    () => onSave(new ObjectRecord(newObject)),
                    onCancel,
                    newObject, new FormController(recordService, new ObjectFormService(newObject, recordService), parentForm.FormController.ApplicationController), parentForm, subGridName, parentForm.OnlyValidate);
                return(viewModel);
                //ideally could hide the parent dialog temporarily and load this one
            }
            //if the object specifies use a form then use the form/dialog
            else
            {
                return(null);
            }
        }
        public void WriteObject(object objectToWrite)
        {
            var objectRecord  = new ObjectRecord(objectToWrite);
            var recordService = new ObjectRecordService(objectToWrite, null);
            var formService   = new ObjectFormService(objectToWrite, recordService);
            var formMetadata  = formService.GetFormMetadata(objectToWrite.GetType().AssemblyQualifiedName);

            foreach (var section in formMetadata.FormSections.OrderBy(s => s.Order))
            {
                if (section is FormFieldSection fieldSection)
                {
                    if (fieldSection.FormFields.Any(f => objectToWrite.IsInContext(f.FieldName)))
                    {
                        _content.AppendLine("<p>");
                        if (fieldSection.DisplayLabel)
                        {
                            AppendSectionHeading(fieldSection.SectionLabel);
                        }
                        foreach (var field in fieldSection.FormFields.OrderBy(f => f.Order))
                        {
                            if (objectToWrite.IsInContext(field.FieldName))
                            {
                                if (field.DisplayLabel)
                                {
                                    AppendFieldHeading(recordService.GetFieldLabel(field.FieldName, objectRecord.Type));
                                }
                                if (recordService.GetFieldType(field.FieldName, objectRecord.Type) == RecordFieldType.Enumerable)
                                {
                                    //okay need to generate a table
                                    var enumerableMetadata = recordService.GetFieldMetadata(field.FieldName, objectRecord.Type) as EnumerableFieldMetadata;
                                    var gridFieldMetadata  = recordService.GetGridFields(enumerableMetadata.EnumeratedTypeQualifiedName, ViewType.AssociatedView);
                                    var table = new StringBuilder();
                                    table.AppendLine("<table>");
                                    table.AppendLine("<thead><tr>");

                                    var fieldJustifies = new Dictionary <string, string>();
                                    foreach (var gridField in gridFieldMetadata)
                                    {
                                        var justify     = recordService.GetFieldType(gridField.FieldName, enumerableMetadata.EnumeratedTypeQualifiedName).GetHorizontalJustify(true);
                                        var htmlJustify = justify == HorizontalJustify.Left
                                            ? "left"
                                            : justify == HorizontalJustify.Middle
                                            ? "center"
                                            : "right";
                                        fieldJustifies.Add(gridField.FieldName, htmlJustify);
                                    }

                                    foreach (var gridField in gridFieldMetadata)
                                    {
                                        table.AppendLine($"<th width={gridField.WidthPart} {thStyle.Replace("left", fieldJustifies[gridField.FieldName])}>{recordService.GetFieldLabel(gridField.FieldName, enumerableMetadata.EnumeratedTypeQualifiedName)}</th>");
                                    }
                                    table.AppendLine("</tr></thead>");

                                    var linkedObjects = recordService
                                                        .GetLinkedRecords(enumerableMetadata.EnumeratedTypeQualifiedName, objectRecord.Type, field.FieldName, objectRecord.Id)
                                                        .Cast <ObjectRecord>()
                                                        .ToArray();
                                    var objectsForTable = linkedObjects
                                                          .Take(MaximumNumberOfEntitiesToList)
                                                          .ToArray();

                                    foreach (var gridRecord in objectsForTable.Take(MaximumNumberOfEntitiesToList))
                                    {
                                        table.AppendLine("<tr>");
                                        foreach (var gridField in gridFieldMetadata
                                                 .Where(gf => objectsForTable.Any(o => o.Instance.IsInContext(gf.FieldName))))
                                        {
                                            table.AppendLine(string.Format("<td {0}>", tdStyle.Replace("left", fieldJustifies[gridField.FieldName])));
                                            table.Append(recordService.GetFieldAsDisplayString(gridRecord, gridField.FieldName));
                                            table.AppendLine("</td>");
                                        }
                                        table.AppendLine("</tr>");
                                    }
                                    table.AppendLine("</table>");
                                    _content.AppendLine(table.ToString());

                                    if (linkedObjects.Count() > MaximumNumberOfEntitiesToList)
                                    {
                                        AppendParagraph(string.Format("Note this list is incomplete as the maximum of {0} items has been listed", MaximumNumberOfEntitiesToList));
                                    }
                                }
                                else
                                {
                                    AppendFieldValue(recordService.GetFieldAsDisplayString(objectRecord, field.FieldName));
                                }
                            }
                        }
                        _content.AppendLine("</p>");
                    }
                }
            }
        }
        public override FormMetadata GetFormMetadata(string recordType, IRecordService recordService = null)
        {
            if (_formMetadata == null)
            {
                var formSections = new List <FormFieldSection>();

                var type             = ObjectToEnter.GetType();
                var propertyMetadata = ObjectRecordService.GetFieldMetadata(type.AssemblyQualifiedName);

                var standardFieldSectionName = type.GetDisplayName();

                var fieldSections = type.GetCustomAttributes <Group>();
                var otherSections = new Dictionary <string, List <FormFieldMetadata> >();
                foreach (var section in fieldSections)
                {
                    var functions = new List <CustomFormFunction>();
                    if (section.SelectAll)
                    {
                        functions.Add(new CustomFormFunction("SELECTALL", "SELECT ALL", (re) =>
                        {
                            var entryForm = re as RecordEntryFormViewModel;
                            if (entryForm != null)
                            {
                                var thisSection   = entryForm.GetFieldSection(section.Name);
                                var booleanFields = thisSection.Fields.Where(f => f is BooleanFieldViewModel).Cast <BooleanFieldViewModel>();
                                var turnOff       = booleanFields.All(b => b.Value);
                                foreach (var field in booleanFields)
                                {
                                    field.Value = !turnOff;
                                }
                            }
                        }));
                    }
                    otherSections[section.Name] = new List <FormFieldMetadata>();
                    var newSection = new FormFieldSection(section.Name, otherSections[section.Name], section.DisplayLayout, section.Order, customFunctions: functions);
                    formSections.Add(newSection);
                }

                foreach (var property in propertyMetadata.Where(m => m.Readable || m.Writeable))
                {
                    var propinfo       = ObjectRecordService.GetPropertyInfo(property.SchemaName, type.AssemblyQualifiedName);
                    var groupAttribute = propinfo.GetCustomAttribute <Group>();

                    string enumerableType = null;
                    if (property is EnumerableFieldMetadata)
                    {
                        enumerableType = ((EnumerableFieldMetadata)property).EnumeratedTypeQualifiedName;
                    }

                    var displayLabel = property.FieldType != RecordFieldType.Enumerable ||
                                       groupAttribute != null;

                    var fieldMetadata = new PersistentFormField(property.SchemaName, enumerableType, displayLabel);
                    fieldMetadata.Order = property.Order;

                    string sectionName = null;
                    if (groupAttribute != null)
                    {
                        sectionName = groupAttribute.Name;
                    }
                    else if (property.FieldType == RecordFieldType.Enumerable)
                    {
                        sectionName = property.DisplayName;
                    }
                    else
                    {
                        sectionName = standardFieldSectionName;
                    }

                    var order = 0;
                    if (groupAttribute != null)
                    {
                        order = groupAttribute.Order;
                    }
                    else if (property.FieldType == RecordFieldType.Enumerable)
                    {
                        order = 200000;
                    }
                    else
                    {
                        order = 1;
                    }

                    var displayLayout = groupAttribute != null
                        ? groupAttribute.DisplayLayout
                        : Group.DisplayLayoutEnum.VerticalList;

                    if (!otherSections.ContainsKey(sectionName))
                    {
                        otherSections[sectionName] = new List <FormFieldMetadata>();
                        var newSection = new FormFieldSection(sectionName, otherSections[sectionName], displayLayout, order);
                        formSections.Add(newSection);
                    }
                    otherSections[sectionName].Add(fieldMetadata);
                }
                foreach (var section in formSections)
                {
                    var fields = section.FormFields;
                    if (section.DisplayLayout == Group.DisplayLayoutEnum.HorizontalInputOnly)
                    {
                        foreach (var field in fields)
                        {
                            field.DisplayLabel = false;
                        }
                    }
                    if (fields.Count() == 1)
                    {
                        var field   = fields.First();
                        var fieldMt = ObjectRecordService.GetFieldMetadata(field.FieldName, type.AssemblyQualifiedName);
                        if (fieldMt is EnumerableFieldMetadata ||
                            fieldMt is MemoFieldMetadata ||
                            (fieldMt is StringFieldMetadata && fieldMt.IsMultiline()))
                        {
                            field.DisplayLabel = false;
                        }
                    }
                }
                formSections  = formSections.OrderBy(s => s.Order).ToList();
                _formMetadata = new FormMetadata(formSections);
            }
            return(_formMetadata);
        }