private void AppendInitialiseAttributes(string fieldName, string recordType, List <Action <RecordEntryViewModelBase> > onChanges)
 {
     foreach (var property in ObjectRecordService.GetFields(recordType))
     {
         var propertyInfo            = ObjectRecordService.GetPropertyInfo(property, recordType);
         var initialiseForAttributes = propertyInfo
                                       .GetCustomAttributes <InitialiseFor>()
                                       .Where(a => a.PropertyDependency == fieldName);
         if (initialiseForAttributes.Any())
         {
             onChanges.Add((re) =>
             {
                 foreach (var initialiseForAttribute in initialiseForAttributes)
                 {
                     var dependencyViewModel = re.GetFieldViewModel(fieldName);
                     var dependantViewModel  = re.GetFieldViewModel(propertyInfo.Name);
                     if (dependencyViewModel.ValueObject != null &&
                         dependencyViewModel.ValueObject.Equals(initialiseForAttribute.ForValue) &&
                         (initialiseForAttribute.AlwaysSetIfNotEmpty || dependantViewModel.ValueObject.IsEmpty()))
                     {
                         dependantViewModel.ValueObject = initialiseForAttribute.InitialValue;
                     }
                 }
             });
         }
     }
 }
        public ObjectFieldViewModel(string fieldName, string fieldLabel, RecordEntryViewModelBase recordForm,
                                    bool usePicklist)
            : base(fieldName, fieldLabel, recordForm, usePicklist)
        {
            //okay i need to identify that this is getting the lookups from the settings
            SettingsAttribute = GetSettingLookupAttribute();
            if (SettingsAttribute == null)
            {
                //throw new NotImplementedException(
                //    string.Format(
                //        "The {0} Type Has Only Been Implemented For Object Properties With {1} Attribute. You Will Need To Review Instantiating a Different Type Of View Model For The {2} Type Of You Property {3} Or Extending It For Your Needs",
                //        typeof(ObjectFieldViewModel).Name, typeof(SettingsLookup).Name, RecordTypeToLookup, FieldName));
            }
            else
            {
                var settingsObject = GetSettingsObject();

                XrmButton = new XrmButtonViewModel("Search", Search, ApplicationController);
                if (settingsObject != null)
                {
                    _lookupService = new ObjectRecordService(settingsObject, ApplicationController, GetObjectRecordService().ObjectTypeMaps);
                    if (!UsePicklist)
                    {
                        LoadLookupGrid();
                    }
                }

                SetNewAction();
            }
        }
 private void AppendDisplayNameAttributes(string fieldName, string recordType, List <Action <RecordEntryViewModelBase> > onChanges)
 {
     foreach (var property in ObjectRecordService.GetFields(recordType))
     {
         var propertyInfo = ObjectRecordService.GetPropertyInfo(property, recordType);
         var attributes   = propertyInfo
                            .GetCustomAttributes <DisplayNameForPropertyValueAttribute>()
                            .Where(a => a.Property == fieldName);
         if (attributes.Any())
         {
             onChanges.Add((re) =>
             {
                 foreach (var attribute in attributes)
                 {
                     var dependencyViewModel = re.GetFieldViewModel(fieldName);
                     var dependantViewModel  = re.GetFieldViewModel(propertyInfo.Name);
                     if (dependencyViewModel.ValueObject != null &&
                         dependencyViewModel.ValueObject.Equals(attribute.Value))
                     {
                         dependantViewModel.Label = attribute.Label;
                     }
                 }
             });
         }
     }
 }
        private void AppendUniqueOnAttributes(string fieldName, string recordType, List <Action <RecordEntryViewModelBase> > onChanges)
        {
            var attributes = ObjectRecordService.GetPropertyInfo(fieldName, recordType).GetCustomAttribute <UniqueOn>();

            if (attributes != null)
            {
                onChanges.Add(
                    re => re.StartNewAction(() =>
                {
                    //just need to if this in a grid then set all others off
                    if (re is GridRowViewModel)
                    {
                        var gridRowViewModel = (GridRowViewModel)re;
                        var fieldViewModel   = gridRowViewModel.GetFieldViewModel(fieldName) as BooleanFieldViewModel;
                        if (fieldViewModel != null && fieldViewModel.Value)
                        {
                            foreach (var row in gridRowViewModel.GridViewModel.GridRecords.ToArray())
                            {
                                if (row != gridRowViewModel)
                                {
                                    ((BooleanFieldViewModel)row.GetFieldViewModel(fieldName)).Value = false;
                                }
                            }
                        }
                    }
                }));
            }
        }
 public static ObjectRecordService GetTheService()
 {
     if (_theService == null)
     {
         _theService = new ObjectRecordService(GetTheObject(), GetTheApplicationController());
     }
     return(_theService);
 }
        public static FormController CreateForObject(object objectToEnter, IApplicationController applicationController, IRecordService lookupService, IDictionary <string, IEnumerable <string> > optionSetLimitedvalues = null)
        {
            var recordService  = new ObjectRecordService(objectToEnter, lookupService, optionSetLimitedvalues, applicationController);
            var formService    = new ObjectFormService(objectToEnter, recordService);
            var formController = new FormController(recordService, formService, applicationController);

            return(formController);
        }
示例#7
0
        protected override void LoadDialogExtention()
        {
            var recordService = new ObjectRecordService(ObjectToEnter, LookupService, OptionsetLimitedValues, ApplicationController, ObjectTypeMaps);
            var formService   = new ObjectFormService(ObjectToEnter, recordService, ObjectTypeMaps);

            ViewModel = new ObjectEntryViewModel(StartNextAction, OnCancel, ObjectToEnter,
                                                 new FormController(recordService, formService, ApplicationController), OnlyValidate);
            Controller.LoadToUi(ViewModel);
        }
        private void DownloadTemplates(RecordEntryFormViewModel viewModel)
        {
            //okay so something to generate one or more csv files with column headings
            //think will just create a child form entry, generate on save then return to the dialog form
            try
            {
                if (viewModel is ObjectEntryViewModel)
                {
                    var oevm = viewModel as ObjectEntryViewModel;

                    var templatesRequest = new GenerateTemplatesRequest();

                    //this is the save function after entering the csvs to generate
                    Action createTemplatesAndReturn = () =>
                    {
                        var serviceConnection = viewModel.RecordService.LookupService;
                        //loop through each csv entered and create
                        foreach (var config in templatesRequest.CsvsToGenerate)
                        {
                            var recordType      = config.RecordType.Key;
                            var fieldsInEntity  = serviceConnection.GetFields(recordType).ToArray();
                            var fieldsToInclude = config.AllFields
                            ? fieldsInEntity
                                                  .Where(f =>
                            {
                                var mt = serviceConnection.GetFieldMetadata(f, recordType);
                                return(mt.Createable || mt.Writeable);
                            }).ToArray()
                                : config.FieldsToInclude.Select(f => f.RecordField.Key).Intersect(fieldsInEntity).ToArray();

                            var columnHeadings = templatesRequest.UseSchemaNames ? fieldsToInclude : fieldsToInclude.Select(f => serviceConnection.GetFieldLabel(f, recordType)).ToArray();

                            var csvText       = string.Join(",", columnHeadings.OrderBy(s => s));
                            var fileNameNoExt = templatesRequest.UseSchemaNames ? recordType : serviceConnection.GetCollectionName(recordType);
                            FileUtility.WriteToFile(templatesRequest.FolderToSaveInto.FolderPath, fileNameNoExt + ".csv", csvText);
                        }
                        viewModel.ApplicationController.StartProcess("explorer", templatesRequest.FolderToSaveInto.FolderPath);
                        //reload the form and notify
                        viewModel.ClearChildForms();
                        viewModel.LoadCustomFunctions();
                    };

                    //load the entry form
                    var os  = new ObjectRecordService(templatesRequest, viewModel.RecordService.LookupService, null, viewModel.ApplicationController, null);
                    var ofs = new ObjectFormService(templatesRequest, os, null);
                    var fc  = new FormController(os, ofs, viewModel.ApplicationController);

                    var vm = new ObjectEntryViewModel(createTemplatesAndReturn, () => viewModel.ClearChildForms(), templatesRequest, fc);
                    viewModel.LoadChildForm(vm);
                }
            }
            catch (Exception ex)
            {
                ApplicationController.ThrowException(ex);
            }
        }
        public override Action GetBulkAddFunctionFor(string referenceName, RecordEntryViewModelBase recordForm)
        {
            var functions      = new Dictionary <string, Action>();
            var enumeratedType = ObjectRecordService.GetPropertyType(referenceName, recordForm.GetRecordType()).GenericTypeArguments[0];
            var customFunction = enumeratedType.GetCustomAttribute <BulkAddFunction>();

            return(customFunction != null
                ? customFunction.GetCustomFunction(recordForm, referenceName)
                : null);
        }
        public ObjectEntryViewModel LoadToObjectEntryViewModel(object objectToEnter)
        {
            var applicationController = new FakeApplicationController();
            var recordService         = new ObjectRecordService(objectToEnter, applicationController);
            var formService           = new ObjectFormService(objectToEnter, recordService);
            var viewModel             = new ObjectEntryViewModel(EmptyMethod, EmptyMethod, objectToEnter,
                                                                 new FormController(recordService, formService, applicationController));

            viewModel.LoadFormSections();
            Assert.IsNotNull(viewModel.FormSectionsAsync);
            return(viewModel);
        }
 public override IEnumerable <ValidationRuleBase> GetSectionValidationRules(string sectionIdentifier)
 {
     if (ObjectType.GetProperty(sectionIdentifier) != null)
     {
         return
             (ObjectRecordService.GetValidatorAttributes(sectionIdentifier, ObjectType.AssemblyQualifiedName)
              .Select(va => new PropertyAttributeValidationRule(va)));
     }
     else
     {
         return(new ValidationRuleBase[0]);
     }
 }
        internal override IEnumerable <CustomFormFunction> GetCustomFunctions(string recordType, RecordEntryFormViewModel recordForm)
        {
            var type = ObjectRecordService.GetClassType(recordType);
            var customGridFunctions = new List <CustomFormFunction>();
            var typesToResolve      = GetTypesToResolve(type);

            foreach (var typeToResolve in typesToResolve)
            {
                var injectedFunctions = recordForm.ApplicationController.ResolveInstance(typeof(CustomFormFunctions), typeToResolve.AssemblyQualifiedName) as CustomFormFunctions;
                customGridFunctions.AddRange(injectedFunctions.CustomFunctions);
            }
            return(customGridFunctions);
        }
示例#13
0
        protected override void LoadDialogExtention()
        {
            LoadingViewModel.LoadingMessage = "Loading Entry Form";
            var recordService = new ObjectRecordService(ObjectToEnter, LookupService, OptionsetLimitedValues, ApplicationController, ObjectTypeMaps);
            var formService   = new ObjectFormService(ObjectToEnter, recordService, ObjectTypeMaps);

            ViewModel = new ObjectEntryViewModel(StartNextAction, OnCancel, ObjectToEnter,
                                                 new FormController(recordService, formService, ApplicationController), OnlyValidate, saveButtonLabel: SaveButtonLabel, cancelButtonLabel: CancelButtonLabel);
            if (InitialMessage != null)
            {
                ViewModel.ValidationPrompt = InitialMessage;
            }
            Controller.LoadToUi(ViewModel);
        }
        public override IEnumerable <ValidationRuleBase> GetValidationRules(string fieldName, string recordType)
        {
            var validators    = new List <ValidationRuleBase>();
            var type          = ObjectRecordService.GetPropertyType(fieldName, ObjectType.AssemblyQualifiedName);
            var isValidatable = type.IsTypeOf(typeof(IValidatableObject));

            if (isValidatable)
            {
                validators.Add(new IValidatableObjectValidationRule());
            }
            validators.AddRange(ObjectRecordService.GetValidatorAttributes(fieldName, ObjectType.AssemblyQualifiedName)
                                .Select(va => new PropertyAttributeValidationRule(va)));
            return(validators);
        }
        public override IEnumerable <Condition> GetLookupConditions(string fieldName, string recordType, string reference, IRecord record)
        {
            var propertyInfo = GetPropertyInfo(fieldName, recordType);
            var attr         = propertyInfo.GetCustomAttributes <LookupCondition>();
            var conditions   = attr == null
                ? new Condition[0].ToList()
                : attr.Select(a => a.ToCondition()).ToList();
            var otherCondition = ObjectRecordService.GetLookupConditionFors(fieldName, recordType, reference, record);

            if (otherCondition != null)
            {
                conditions.Add(otherCondition);
            }
            return(conditions);
        }
示例#16
0
        private void SetNewAction()
        {
            if (SettingsAttribute.AllowAddNew)
            {
                NewAction = () =>
                {
                    var settingsObject   = GetSettingsObject();
                    var propertyInfo     = settingsObject.GetType().GetProperty(SettingsAttribute.PropertyName);
                    var enumerateType    = propertyInfo.PropertyType.GenericTypeArguments[0];
                    var newSettingObject = enumerateType.CreateFromParameterlessConstructor();

                    var objectRecordService = new ObjectRecordService(newSettingObject, ApplicationController, null);
                    var formService         = new ObjectFormService(newSettingObject, objectRecordService);
                    var formController      = new FormController(objectRecordService, formService, ApplicationController);

                    Action onSave = () =>
                    {
                        //add the new item to the permanent settings
                        var settingsManager = ApplicationController.ResolveType <ISettingsManager>();
                        settingsObject = GetSettingsObject();
                        var settingsService = new ObjectRecordService(settingsObject, ApplicationController);
                        var currentSettings = settingsService.RetrieveAll(enumerateType.AssemblyQualifiedName, null)
                                              .Select(r => ((ObjectRecord)r).Instance)
                                              .ToList();
                        currentSettings.Add(newSettingObject);
                        settingsObject.SetPropertyValue(SettingsAttribute.PropertyName, enumerateType.ToNewTypedEnumerable(currentSettings));
                        settingsManager.SaveSettingsObject(settingsObject);
                        ValueObject = newSettingObject;
                        if (UsePicklist)
                        {
                            //reload the picklist
                            ValueObject = newSettingObject;
                            LoadPicklistItems();
                        }
                        else
                        {
                            SetEnteredTestWithoutClearingValue(ValueObject.ToString());
                        }
                        RecordEntryViewModel.ClearChildForm();
                    };

                    var newSettingForm = new ObjectEntryViewModel(onSave, RecordEntryViewModel.ClearChildForm, newSettingObject, formController);
                    RecordEntryViewModel.LoadChildForm(newSettingForm);
                };
            }
        }
        private void AppendReadOnlyWhenSetAttributes(string fieldName, string recordType, List <Action <RecordEntryViewModelBase> > onChanges)
        {
            var attributes = ObjectRecordService.GetPropertyInfo(fieldName, recordType).GetCustomAttribute <ReadOnlyWhenSet>();

            if (attributes != null)
            {
                onChanges.Add(
                    re => re.StartNewAction(() =>
                {
                    //just need to if this in a grid then set all others off
                    var fieldViewModel = re.GetFieldViewModel(fieldName);
                    if (fieldViewModel != null)
                    {
                        fieldViewModel.IsEditable = fieldViewModel.ValueObject == null;
                    }
                }));
            }
        }
        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);
                    }
                }));
            }
        }
        public override RecordEntryFormViewModel GetEditRowViewModel(string subGridName, RecordEntryViewModelBase parentForm, Action <IRecord> onSave, Action onCancel, GridRowViewModel gridRow)
        {
            var record = gridRow.GetRecord();

            if (!(record is ObjectRecord))
            {
                throw new NotSupportedException(string.Format("Error Expected Object Of Type {0}", typeof(ObjectRecord).Name));
            }
            var newRecord = (ObjectRecord)record;
            //need to load the existing row to this
            //lets start a dialog to add it on complete
            var mapper        = new ClassSelfMapper();
            var newObject     = mapper.Map(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);
        }
        private void AppendCascadeOnChanges(string fieldName, string recordType, List <Action <RecordEntryViewModelBase> > onChanges)
        {
            var lookupForAttributes = ObjectRecordService.GetPropertyInfo(fieldName, recordType)
                                      .GetCustomAttributes(typeof(CascadeOnChange), true).Cast <CascadeOnChange>();

            foreach (var attribute in lookupForAttributes)
            {
                onChanges.Add(
                    re =>
                {
                    var changedViewModel = re.GetFieldViewModel(fieldName);
                    if (changedViewModel.ValueObject != null)
                    {
                        var matchingFields = re.FieldViewModels.Where(f => f.FieldName == attribute.TargetProperty);
                        if (matchingFields.Any())
                        {
                            matchingFields.First().ValueObject = changedViewModel.ValueObject;
                        }
                    }
                });
            }
        }
        private void AppendConnectionForChanges(string fieldName, string recordType, List <Action <RecordEntryViewModelBase> > onChanges, bool isOnLoad)
        {
            var lookupForAttributes = ObjectRecordService.GetPropertyInfo(fieldName, recordType)
                                      .GetCustomAttributes(typeof(ConnectionFor), true).Cast <ConnectionFor>();

            foreach (var attribute in lookupForAttributes)
            {
                onChanges.Add(
                    re =>
                {
                    var changedViewModel = re.GetFieldViewModel(fieldName);
                    if (changedViewModel.ValueObject != null)
                    {
                        var matchingFields =
                            re.FieldViewModels.Where(f => f.FieldName == attribute.Property);
                        if (matchingFields.Any())
                        {
                            var fieldViewModel = matchingFields.First();
                            if (!isOnLoad && fieldViewModel is LookupFieldViewModel)
                            {
                                var typedViewModel = (LookupFieldViewModel)fieldViewModel;
                                typedViewModel.ConnectionForChanged();
                            }
                            if (fieldViewModel is RecordTypeFieldViewModel)
                            {
                                var typedViewModel         = (RecordTypeFieldViewModel)fieldViewModel;
                                typedViewModel.ItemsSource = ObjectRecordService
                                                             .GetPicklistKeyValues(fieldViewModel.FieldName,
                                                                                   fieldViewModel.GetRecordType())
                                                             .Select(p => new RecordType(p.Key, p.Value))
                                                             .Where(rt => !rt.Value.IsNullOrWhiteSpace())
                                                             .OrderBy(rt => rt.Value)
                                                             .ToArray();
                            }
                        }
                    }
                });
            }
        }
        private void AppendLookupFieldCascadeChanges(string fieldName, string recordType, List <Action <RecordEntryViewModelBase> > onChanges)
        {
            var lookupForAttributes = ObjectRecordService.GetPropertyInfo(fieldName, recordType)
                                      .GetCustomAttributes(typeof(LookupFieldCascade), true).Cast <LookupFieldCascade>();

            foreach (var attribute in lookupForAttributes)
            {
                onChanges.Add(
                    re =>
                {
                    var changedViewModel = re.GetFieldViewModel(fieldName);
                    if (changedViewModel.ValueObject != null)
                    {
                        var changedViewModelLookup = ((LookupFieldViewModel)changedViewModel).Value;
                        var matchingFields         = re.FieldViewModels.Where(f => f.FieldName == attribute.TargetProperty);
                        var lookupService          = ObjectRecordService.GetLookupService(changedViewModel.FieldName, re.GetRecordType(), re.ParentFormReference, re.GetRecord());
                        if (lookupService != null)
                        {
                            var lookupRecord = lookupService.Get(changedViewModelLookup.RecordType, changedViewModelLookup.Id);
                            if (lookupRecord == null)
                            {
                                changedViewModel.ValueObject = null;
                                re.ApplicationController.UserMessage(string.Format("The {0} Was Not Found And The Value Has Been Cleared", changedViewModel.Label));
                            }
                            else
                            {
                                var sourceFieldValue = lookupRecord.GetField(attribute.SourceRecordField);
                                if (matchingFields.Any())
                                {
                                    matchingFields.First().ValueObject = sourceFieldValue;
                                }
                            }
                        }
                    }
                });
            }
        }
        internal void SetItemsSource(IEnumerable <T> items)
        {
            ItemsSource = items == null ? new SelectablePicklistOption[0] : items.Select(i => new SelectablePicklistOption(i, RefreshSelectedItemsIntoValue, Value != null && Value.Any(v => v == i))).ToArray();
            var optionsObject = new SelectablePicklistOptions()
            {
                Options = ItemsSource
            };
            var recordService = new ObjectRecordService(optionsObject, ApplicationController);
            Func <IEnumerable <IRecord> > getRecordsFunc = () => recordService.RetreiveAll(new QueryDefinition(typeof(SelectablePicklistOption).AssemblyQualifiedName));

            DynamicGridViewModel = new DynamicGridViewModel(ApplicationController)
            {
                ViewType       = ViewType.LookupView,
                FormController = new FormController(recordService, null, ApplicationController),
                RecordType     = typeof(SelectablePicklistOption).AssemblyQualifiedName,
                RecordService  = recordService,
                GetGridRecords = (b) => new GetGridRecordsResponse(getRecordsFunc()),
                IsReadOnly     = true
            };
            Action onClick = () =>
            {
                var selectedItem = DynamicGridViewModel.SelectedRow;
                if (selectedItem != null)
                {
                    var isSelectedField = selectedItem.GetBooleanFieldFieldViewModel(nameof(SelectablePicklistOption.Select));
                    isSelectedField.Value            = !isSelectedField.Value;
                    DynamicGridViewModel.SelectedRow = null;
                }
            };

            DynamicGridViewModel.OnClick = onClick;
            DoOnAsynchThread(() => {
                DynamicGridViewModel.GridRecords = GridRowViewModel.LoadRows(getRecordsFunc(), DynamicGridViewModel);
                OnPropertyChanged(nameof(DynamicGridViewModel));
                OnPropertyChanged(nameof(StringDisplay));
            });
        }
        internal override IEnumerable <CustomGridFunction> GetCustomFunctionsFor(string referenceName, RecordEntryFormViewModel recordForm)
        {
            var functions  = new Dictionary <string, Action>();
            var recordType = recordForm.GetEnumerableFieldViewModel(referenceName).RecordType;

            if (recordType == null)
            {
                return(new CustomGridFunction[0]);
            }

            var enumeratedType  = ObjectRecordService.GetClassType(recordType);
            var customFunctions = enumeratedType.GetCustomAttributes <CustomFunction>();

            if (customFunctions != null)
            {
                foreach (var item in customFunctions)
                {
                    functions.Add(item.GetFunctionLabel(), item.GetCustomFunction(recordForm, referenceName));
                }
            }
            var allowDownloadAttribute = ObjectRecordService.GetPropertyInfo(referenceName, recordForm.RecordType).GetCustomAttribute <AllowDownload>();

            if (allowDownloadAttribute != null)
            {
                functions.Add("Download CSV", () => { recordForm.GetEnumerableFieldViewModel(referenceName).DynamicGridViewModel.DownloadCsv(); });
            }
            var customGridFunctions = functions.Select(kv => new CustomGridFunction(kv.Key, kv.Key, kv.Value)).ToList();
            var typesToResolve      = GetTypesToResolve(enumeratedType);

            foreach (var typeToResolve in typesToResolve)
            {
                var injectedFunctions = recordForm.ApplicationController.ResolveInstance(typeof(CustomGridFunctions), typeToResolve.AssemblyQualifiedName) as CustomGridFunctions;
                customGridFunctions.AddRange(injectedFunctions.CustomFunctions);
            }
            return(customGridFunctions);
        }
        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);
            }
        }
        private void AppendFieldForChanges(string fieldName, string recordType, List <Action <RecordEntryViewModelBase> > onChanges, bool clearValue = false)
        {
            var lookupForAttributes = ObjectRecordService.GetPropertyInfo(fieldName, recordType)
                                      .GetCustomAttributes(typeof(RecordFieldFor), true).Cast <RecordFieldFor>();

            foreach (var attribute in lookupForAttributes)
            {
                onChanges.Add(
                    re => re.StartNewAction(() =>
                {
                    var recordFieldViewModel = re.GetRecordFieldFieldViewModel(fieldName);
                    if (recordFieldViewModel.Value != null)
                    {
                        var matchingFields = re.FieldViewModels.Where(f => f.FieldName == attribute.PropertyPaths.First());
                        foreach (var fieldViewModel in matchingFields.ToArray())
                        {
                            var selectedFieldName       = recordFieldViewModel.Value.Key;
                            var selectedFieldRecordType = GetRecordTypeFor(recordFieldViewModel.FieldName, re);
                            var lookupService           = re.RecordService.GetLookupService(recordFieldViewModel.FieldName, recordFieldViewModel.GetRecordType(), null, recordFieldViewModel.RecordEntryViewModel.GetRecord());
                            if (lookupService != null)
                            {
                                //get the source field type
                                var fieldType = lookupService.GetFieldType(selectedFieldName, selectedFieldRecordType);
                                //get the section the target field is in and its field metadata
                                var metadata = re.FormService.GetFormMetadata(re.GetRecordType(), ObjectRecordService);
                                FormFieldMetadata fieldMetadata = null;
                                string sectionName = null;
                                foreach (var sectionMetadata in metadata.FormSections.Cast <FormFieldSection>())
                                {
                                    foreach (var field in sectionMetadata.FormFields)
                                    {
                                        if (field.FieldName == fieldViewModel.FieldName)
                                        {
                                            sectionName   = sectionMetadata.SectionLabel;
                                            fieldMetadata = field;
                                        }
                                    }
                                }
                                if (!string.IsNullOrWhiteSpace(sectionName))
                                {
                                    var targetPropInfo = ObjectRecordService.GetPropertyType(attribute.PropertyPaths.First(), recordType);
                                    if (targetPropInfo.IsEnum)
                                    {
                                        //if target is an enum then filter the items source for the field type
                                        var picklistFieldViewModel = fieldViewModel as PicklistFieldViewModel;
                                        var picklistOptions        = ObjectRecordService.GetPicklistKeyValues(picklistFieldViewModel.FieldName, picklistFieldViewModel.GetRecordType(), fieldType.ToString(), picklistFieldViewModel.RecordEntryViewModel.GetRecord());
                                        if (clearValue)
                                        {
                                            picklistFieldViewModel.Value = null;
                                        }
                                        picklistFieldViewModel.ItemsSource = picklistOptions;
                                    }
                                    else
                                    {
                                        //otherwise is a field input dynamic for the field's tpye
                                        //now we need to create the view model for the target field as the correct type
                                        //okay now we need to replace the old field view model for this field
                                        var explicitTargetType = fieldType == RecordFieldType.Lookup || fieldType == RecordFieldType.Customer || fieldType == RecordFieldType.Owner
                                                ? lookupService.GetLookupTargetType(selectedFieldName, selectedFieldRecordType)
                                                : null;
                                        var explicitPicklistOptions = fieldType == RecordFieldType.Picklist ||
                                                                      fieldType == RecordFieldType.Status ||
                                                                      fieldType == RecordFieldType.State ||
                                                                      fieldType == RecordFieldType.Integer
                                                ? lookupService.GetPicklistKeyValues(selectedFieldName, selectedFieldRecordType)
                                                : null;
                                        if (clearValue)
                                        {
                                            fieldViewModel.ValueObject = null;
                                        }
                                        var newFieldViewModel = fieldMetadata.CreateFieldViewModel(re.GetRecordType(), re.RecordService, re, re.ApplicationController, explicitFieldType: fieldType, explicitLookupTargetType: explicitTargetType, explicitPicklistOptions: explicitPicklistOptions);
                                        var section           = re.FieldSections.First(s => s.SectionLabel == sectionName);
                                        var index             = section.Fields.Count;
                                        for (var i = 0; i < section.Fields.Count; i++)
                                        {
                                            if (section.Fields[i].FieldName == fieldViewModel.FieldName)
                                            {
                                                index = i;
                                                break;
                                            }
                                        }

                                        re.DoOnMainThread(() =>
                                        {
                                            if (section.Fields.Count > index)
                                            {
                                                section.Fields.RemoveAt(index);
                                            }

                                            if (clearValue)
                                            {
                                                fieldViewModel.ValueObject = null;
                                            }
                                            section.Fields.Insert(index, newFieldViewModel);
                                            re.RefreshVisibility();
                                        });
                                    }
                                }
                            }
                        }
                    }
                }));
            }
        }
        private string GetRecordTypeFor(string field, RecordEntryViewModelBase viewModel)
        {
            var split = field?.Split('.') ?? new string[0];

            if (!split.Any())
            {
                return(null);
            }
            var propertyInfo = GetPropertyInfo(split.First(), viewModel.GetRecord().Type);

            if (propertyInfo != null)
            {
                if (propertyInfo.GetType().Name == "IEnumerable`1" && split.Count() > 1)
                {
                    var enumeratedType = propertyInfo.GetType().GenericTypeArguments[0];
                    propertyInfo = enumeratedType.GetProperty(split.ElementAt(1)) ?? propertyInfo;
                }
                var attribute = propertyInfo.GetCustomAttribute <ReferencedType>();
                if (attribute != null)
                {
                    return(attribute.Type);
                }
            }
            foreach (var parentField in ObjectRecordService.GetPropertyInfos(viewModel.GetRecordType()))
            {
                var lookupForAttributes =
                    parentField.GetCustomAttributes(typeof(RecordTypeFor), true).Cast <RecordTypeFor>();
                foreach (var lookupForAttribute in lookupForAttributes)
                {
                    if (lookupForAttribute.LookupProperty == field)
                    {
                        //can't use the field view model as called on load and may trigger infinite loop loading field list
                        var record = viewModel.GetRecord();
                        if (record is ObjectRecord)
                        {
                            var objectrecord  = (ObjectRecord)record;
                            var propertyValue = objectrecord.Instance.GetPropertyValue(parentField.Name);
                            if (propertyValue is RecordType)
                            {
                                return(((RecordType)propertyValue).Key);
                            }
                        }
                    }
                }
            }
            var parentForm = viewModel.ParentForm;

            if (parentForm is ObjectEntryViewModel)
            {
                foreach (var parentField in ((ObjectEntryViewModel)parentForm).GetObject().GetType().GetProperties())
                {
                    var lookupForAttributes =
                        parentField.GetCustomAttributes(typeof(RecordTypeFor), true).Cast <RecordTypeFor>();
                    foreach (var lookupForAttribute in lookupForAttributes)
                    {
                        if (lookupForAttribute.PropertyPaths.Count() == 2 &&
                            lookupForAttribute.PropertyPaths.First() == viewModel.ParentFormReference &&
                            lookupForAttribute.PropertyPaths.Last() == field)
                        {
                            var parentsFieldViewmOdel = parentForm.GetRecordTypeFieldViewModel(parentField.Name);
                            if (parentsFieldViewmOdel.Value != null)
                            {
                                return(parentsFieldViewmOdel.Value.Key);
                            }
                        }
                    }
                }
            }
            return(null);
        }
        public StringAutocompleteViewModel(StringFieldViewModel stringField, AutocompleteFunction autocompleteFunction)
            : base(stringField.ApplicationController)
        {
            SearchText           = stringField.Value;
            StringField          = stringField;
            AutocompleteFunction = autocompleteFunction;
            var typeAheadOptions = new TypeAheadOptions();

            var typeAheadRecordService = new ObjectRecordService(typeAheadOptions, ApplicationController);
            var formController         = FormController.CreateForObject(typeAheadOptions, ApplicationController, null);

            IEnumerable <object> autoCompleteStrings = null;

            if (AutocompleteFunction.CacheAsStaticList)
            {
                try
                {
                    autoCompleteStrings = autocompleteFunction.GetAutocompleteStrings(StringField.RecordEntryViewModel);
                }
                catch (Exception ex)
                {
                    StringField.AddError($"Error Loading Autocomplete {ex.Message}\n{ex.DisplayString()}");
                }
            }

            Func <bool, GetGridRecordsResponse> getGridRecords = (ignorePages) =>
            {
                try
                {
                    LoadOptionsError    = null;
                    autoCompleteStrings = autoCompleteStrings != null && AutocompleteFunction.CacheAsStaticList
                            ? autoCompleteStrings
                            : autocompleteFunction
                                          .GetAutocompleteStrings(StringField.RecordEntryViewModel);
                    if (autoCompleteStrings == null)
                    {
                        return(new GetGridRecordsResponse(new IRecord[0]));
                    }
                    var searchToLower = SearchText?.ToLower();
                    typeAheadOptions.Options = autoCompleteStrings
                                               .Where(ta => searchToLower == null || AutocompleteFunction.SearchFields.Any(sf => ta.GetPropertyValue(sf)?.ToString().ToLower().StartsWith(searchToLower) ?? false))
                                               .OrderBy(ta => (string)ta.GetPropertyValue(AutocompleteFunction.SortField))
                                               .ThenBy(ta => (string)ta.GetPropertyValue(AutocompleteFunction.ValueField));

                    var records = typeAheadOptions
                                  .Options
                                  .Select(o => new ObjectRecord(o))
                                  .Take(MaxRecordsForLookup)
                                  .ToArray();
                    if (stringField.DisplayAutocomplete &&
                        (!records.Any() ||
                         (records.Count() == 1 && records.First().GetStringField(AutocompleteFunction.ValueField)?.ToLower() == searchToLower)))
                    {
                        stringField.DisplayAutocomplete = false;
                    }
                    else
                    {
                        stringField.DisplayAutocomplete = true;
                    }
                    return(new GetGridRecordsResponse(records));
                }
                catch (Exception ex)
                {
                    LoadOptionsError = $"Autocomplete could not be loaded\n\n{ex.Message}{(ex.InnerException == null ? null : ("\n\n" + ex.InnerException.Message))}\n\n{ex.StackTrace}";
                    return(new GetGridRecordsResponse(new IRecord[0]));
                }
            };

            DynamicGridViewModel = new DynamicGridViewModel(ApplicationController)
            {
                FormController = formController,
                GetGridRecords = getGridRecords,
                OnDoubleClick  = OnDoubleClick,
                ViewType       = ViewType.LookupView,
                RecordService  = typeAheadRecordService,
                RecordType     = AutocompleteFunction.RecordType,
                IsReadOnly     = true,
                DisplayHeaders = false,
                NoMargins      = true,
                FieldMetadata  = AutocompleteFunction.GridFields
            };
        }
        private PropertyInfo GetPropertyInfo(string field, string type)
        {
            var propertyInfo = ObjectRecordService.GetPropertyInfo(field, type);

            return(propertyInfo);
        }
        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>");
                    }
                }
            }
        }