| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063 | using System;using System.Collections.Generic;using System.Threading.Tasks;using System.Threading;using System.Linq;using Xamarin.Forms;using XF.Material.Forms.UI.Dialogs;using InABox.Core;using InABox.Clients;using System.IO;using InABox.Mobile;using Syncfusion.XForms.SignaturePad;using comal.timesheets.Tasks;using Comal.Classes;using PRSClasses;namespace comal.timesheets.QAForms{    public class QAFormViewer : Grid, IDFRenderer    {        #region Fields        public Dictionary<DFLayoutField, View> pairs = new Dictionary<DFLayoutField, View>();        public Dictionary<String, String> results = new Dictionary<String, String>();        public Dictionary<String, String> propertyResults = new Dictionary<String, String>();        Dictionary<String, String> loadData = new Dictionary<String, String>();        public Dictionary<DFLayoutLookupField, Dictionary<Guid, string>> dfLayoutLookupFieldLookupOptions = new Dictionary<DFLayoutLookupField, Dictionary<Guid, string>>();        DFLayout dfLayout = null;        public IDigitalFormDataModel model = null;        const string nullOrInvalidType = "Null or Invalid Type";        int rbGroup;        private Guid userID;        bool isRequired = false;        bool readOnly = false;        bool isSecure = false;        bool loadRetainedForm = false;        List<string> useSavedSignatures = new List<string>();        public List<string> errors = new List<string>();        public bool isRequiredEmpty { get; set; }        public string isRequiredMessage { get; set; }        InABox.Core.Location location = new InABox.Core.Location();        Guid digitalFormID = Guid.Empty;        Color isRequiredColor = Color.DarkOrange;        public string FormData = "";        public DateTime FormCompleted = DateTime.MinValue;        public Guid JobID = Guid.Empty;        DateTime timeStarted = DateTime.MinValue;        List<DigitalFormsHeader> headersToCollapse = new List<DigitalFormsHeader>();        int collapsedHeaderCount = 1;        #endregion        #region Constructor        public QAFormViewer(IDigitalFormDataModel _model, DFLayout _dfLayout, bool newForm, bool _readOnly, Guid _jobid = default(Guid))        {            GetLocation();            timeStarted = DateTime.Now;            userID = ClientFactory.UserGuid;            model = _model;            dfLayout = _dfLayout;            dfLayout.Renderer = this;            readOnly = _readOnly;            isRequiredEmpty = false;            loadRetainedForm = false;            isRequiredMessage = "";            JobID = _jobid;            if (RetainedResults.IsFormRetained)            {                loadRetainedForm = true;            }            if (newForm)            {                LoadForm();            }            else if (!newForm)            {                loadData.Clear();                Dictionary<String, Object> data = DigitalForm.DeserializeFormData(model.Instance);                if (data != null)                {                    foreach (KeyValuePair<string, object> keyValuePair in data)                    {                        loadData.Add(keyValuePair.Key, keyValuePair.Value.ToString());                    }                }                LoadForm();            }        }        #endregion        #region Location        private async void GetLocation()        {            await Task.Run(() =>            {                LocationServices locationServices = new LocationServices();                locationServices.OnLocationFound += LocationFound;                locationServices.OnLocationError += LocationError;                locationServices.GetLocation();            });        }        private async void LocationFound(LocationServices sender)        {            location.Latitude = sender.Latitude;            location.Longitude = sender.Longitude;        }        private async void LocationError(LocationServices sender, Exception error)        {            errors.Add("Location error: " + error.Message);        }        #endregion Location        #region Load Form Layout        private async void LoadForm()        {            using (await MaterialDialog.Instance.LoadingDialogAsync(message: "Loading Form"))            {                LoadRowsAndColumns();                LoadElements();            }        }        private void LoadRowsAndColumns()        {            LoadRows();            LoadColumns();        }        private void LoadRows()        {            foreach (var row in dfLayout.RowHeights)            {                RowDefinition def = new RowDefinition { Height = new GridLength(1, GridUnitType.Auto) };                if (int.TryParse(row, out int rowHeight))                {                    def = new RowDefinition { Height = new GridLength(rowHeight, GridUnitType.Absolute) };                    if (def.Height.Value < 60)                    {                        def.SetValue(RowDefinition.HeightProperty, 60);                    }                }                else if (row == "*")                {                    def = new RowDefinition { Height = new GridLength(1, GridUnitType.Star) };                }                Device.BeginInvokeOnMainThread(() => { RowDefinitions.Add(def); });            }        }        private void LoadColumns()        {            foreach (var col in dfLayout.ColumnWidths)            {                ColumnDefinition def = new ColumnDefinition { Width = new GridLength(1, GridUnitType.Auto) };                if (int.TryParse(col, out int colWidth))                    def = new ColumnDefinition { Width = new GridLength(colWidth, GridUnitType.Absolute) };                else if (col == "*")                {                    def = new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) };                }                Device.BeginInvokeOnMainThread(() => { ColumnDefinitions.Add(def); });            }        }        private void LoadElements()        {            rbGroup = 0; //used for customboolean - has to be outside of foreach loop            foreach (DFLayoutControl element in dfLayout.Elements)            {                if (!string.IsNullOrEmpty(element.Description))                {                    LoadViewAccordingToElement(element);                }            }            Task.Run(() =>            {                Thread.Sleep(1000);                foreach (var header in headersToCollapse)                {                    Device.BeginInvokeOnMainThread(() =>                    {                        AdjustHeaderSection(header, false);                        header.Collapse();                    });                }            });        }        #endregion        #region Load Element Methods        private void LoadViewAccordingToElement(DFLayoutControl element)        {            View view = null;            isSecure = false;            string value = "";            if (element is DFLayoutBooleanField)            {                var tuple = LoadCustomBoolean(view, element, value);                FormatAndAddView(tuple.Item1, element, tuple.Item2);            }            else if (element is DFLayoutLabel)            {                var tuple = LoadLabel(view, element);                FormatAndAddView(tuple.Item1, element, tuple.Item2);            }            else if (element is DFLayoutStringField || element is DFLayoutIntegerField || element is DFLayoutDoubleField)            {                var tuple = LoadEditor(view, element, value);                FormatAndAddView(tuple.Item1, element, tuple.Item2);            }            else if (element is DFLayoutDateField)            {                var tuple = LoadDatePicker(view, element, value);                FormatAndAddView(tuple.Item1, element, tuple.Item2);            }            else if (element is DFLayoutTimeField)            {                var tuple = LoadTimePicker(view, element, value);                FormatAndAddView(tuple.Item1, element, tuple.Item2);            }            else if (element is DFLayoutOptionField)            {                var tuple = LoadOptionPicker(view, element, value);                FormatAndAddView(tuple.Item1, element, tuple.Item2);            }            else if (element is DFLayoutImage)            {                var tuple = LoadImage(view, element);                FormatAndAddView(tuple.Item1, element, tuple.Item2);            }            else if (element is DFLayoutLookupField)            {                var tuple = LoadLookupPicker(view, element, value);                FormatAndAddView(tuple.Item1, element, tuple.Item2);            }            else if (element is DFLayoutSignaturePad)            {                var tuple = LoadSignaturePad(view, element, value);                FormatAndAddView(tuple.Item1, element, tuple.Item2);            }            else if (element is DFLayoutEmbeddedImage)            {                var tuple = LoadEmbeddedImage(view, element, value);                FormatAndAddView(tuple.Item1, element, tuple.Item2);            }            else if (element is DFLayoutMultiImage)            {                var tuple = LoadMultiImage(view, element, value);                FormatAndAddView(tuple.Item1, element, tuple.Item2);            }            else if (element is DFLayoutMultiSignaturePad)            {                var tuple = LoadMultiSignaturePad(view, element, value);                FormatAndAddView(tuple.Item1, element, tuple.Item2);            }            else if (element is DFLayoutAddTaskField)            {                var tuple = LoadAddTaskField(view, element, value);                FormatAndAddView(tuple.Item1, element, tuple.Item2);            }            else if (element is DFLayoutHeader)            {                FormatAndAddView(LoadHeader(view, element), element, false);            }        }        private View LoadHeader(View view, DFLayoutControl element)        {            DFLayoutHeader dFLayoutHeader = (DFLayoutHeader)element;            DigitalFormsHeader header = new DigitalFormsHeader(dFLayoutHeader.Collapsed);            if (dFLayoutHeader.Collapsed)                header = AddNumberToHeader(header);            header.SetHeaderValue(dFLayoutHeader.Header);            header.OnTapped += (bCollapsed) =>            {                AdjustHeaderSection(header, bCollapsed);            };            view = header;            return view;        }        private DigitalFormsHeader AddNumberToHeader(DigitalFormsHeader header)        {            header.Number = collapsedHeaderCount;            collapsedHeaderCount++;            return header;        }        private void AdjustHeaderSection(DigitalFormsHeader header, bool collapsed)        {            try            {                var thisHeaderRow = GetRow(header);                var headerRows = GetOtherHeaders(thisHeaderRow);                if (headerRows.Any())                    AdjustHeightsToNextHeader(headerRows, thisHeaderRow, collapsed);                else                    AdjustHeightsBelowHeader(headerRows, thisHeaderRow, collapsed);            }            catch            {            }        }        private List<int> GetOtherHeaders(int thisHeaderRow)        {            List<int> headerRows = new List<int>();            foreach (var child in Children)            {                if (child is DigitalFormsHeader)                {                    var dfheader = (DigitalFormsHeader)child;                    if (GetRow(dfheader) > thisHeaderRow)                    {                        headerRows.Add(GetRow(dfheader));                    }                }            }            return headerRows;        }        private void AdjustHeightsToNextHeader(List<int> headerRows, int thisHeaderRow, bool collapsed)        {            headerRows.Sort();            int nextHeaderRow = headerRows[0];            for (int i = thisHeaderRow + 1; i < nextHeaderRow; i++)            {                AdjustHeight(i, collapsed);            }        }        private void AdjustHeightsBelowHeader(List<int> headerRows, int thisHeaderRow, bool collapsed)        {            for (int i = thisHeaderRow + 1; i < RowDefinitions.Count; i++)            {                AdjustHeight(i, collapsed);            }        }        private void AdjustHeight(int i, bool collapsed)        {            var rowdef = RowDefinitions[i];            if (collapsed)            {                rowdef.Height = 60;                AnimateChildren(i, 0, 250);            }            else            {                AnimateChildren(i, -60, 500);                rowdef.Height = 0;            }        }        private async void AnimateChildren(int i, int movement, int length)        {            foreach (var child in Children)            {                if (GetRow(child) == i)                {                    await child.TranslateTo(0, movement, 250);                }            }        }        private Tuple<View, Boolean> LoadCustomBoolean(View view, DFLayoutControl element, String value)        {            rbGroup++;            CustomBoolean item = new CustomBoolean(rbGroup);            DFLayoutBooleanField dfLayoutBooleanField = element as DFLayoutBooleanField;            if (!string.IsNullOrWhiteSpace(dfLayoutBooleanField.Properties.TrueValue))                item.trueBtn.Content = dfLayoutBooleanField.Properties.TrueValue;            if (!string.IsNullOrWhiteSpace(dfLayoutBooleanField.Properties.FalseValue))                item.falseBtn.Content = dfLayoutBooleanField.Properties.FalseValue;            if (loadData.TryGetValue(dfLayoutBooleanField.Name, out value))            {                item.Value = bool.Parse(value);                if (bool.Parse(value) == false)                    item.SetFalseValue();            }            if (loadRetainedForm)            {                if (RetainedResults.Results.TryGetValue(dfLayoutBooleanField.Name, out value))                {                    item.Value = bool.Parse(value);                }            }            if (dfLayoutBooleanField.Properties.Required)            {                item.trueBtn.BackgroundColor = isRequiredColor;                item.falseBtn.BackgroundColor = isRequiredColor;            }            item.OnCustomBooleanValueChanged += (boolvalue) =>            {                dfLayout.ChangeField(dfLayoutBooleanField.Name);            };            view = item;            return new Tuple<View, Boolean>(view, dfLayoutBooleanField.Properties.Required);        }        private Tuple<View, Boolean> LoadLabel(View view, DFLayoutControl element)        {            DFLayoutLabel label = element as DFLayoutLabel;            Label item = new Label();            item.Text = label.Caption;            item.FontSize = Device.GetNamedSize(NamedSize.Medium, item);            item.TextColor = Color.Black;            item.LineBreakMode = LineBreakMode.WordWrap;            item.VerticalOptions = LayoutOptions.FillAndExpand;            item.VerticalTextAlignment = TextAlignment.Center;            item.MinimumHeightRequest = 60;            if (ColumnDefinitions.Count == 1)            {                item.HorizontalOptions = LayoutOptions.CenterAndExpand;                item.HorizontalTextAlignment = TextAlignment.Center;            }            view = item;            return new Tuple<View, Boolean>(view, false);        }        private Tuple<View, Boolean> LoadEditor(View view, DFLayoutControl element, string value)        {            Editor item = new Editor();            item.AutoSize = EditorAutoSizeOption.TextChanges;            var isrequired = false;            var issecure = false;            if (element is DFLayoutStringField)            {                DFLayoutStringField dfLayoutStringField = element as DFLayoutStringField;                item.TextColor = Color.Black;                item.Placeholder = "Enter answer";                isrequired = dfLayoutStringField.Properties.Required;                issecure = dfLayoutStringField.Properties.Secure;                if (loadData.TryGetValue(dfLayoutStringField.Name, out value))                {                    item.Text = value;                }                if (loadRetainedForm)                {                    if (RetainedResults.Results.TryGetValue(dfLayoutStringField.Name, out value))                    {                        item.Text = value;                    }                }                item.TextChanged += (object sender, TextChangedEventArgs e) =>                {                    dfLayout.ChangeField(dfLayoutStringField.Name);                };                view = item;            }            else if (element is DFLayoutIntegerField)            {                DFLayoutIntegerField dfLayoutIntegerField = element as DFLayoutIntegerField;                item.TextColor = Color.Black;                item.Placeholder = "Enter number";                item.Keyboard = Keyboard.Numeric;                isrequired = dfLayoutIntegerField.Properties.Required;                issecure = dfLayoutIntegerField.Properties.Secure;                if (loadData.TryGetValue(dfLayoutIntegerField.Name, out value))                {                    item.Text = value;                }                if (loadRetainedForm)                {                    if (RetainedResults.Results.TryGetValue(dfLayoutIntegerField.Name, out value))                    {                        item.Text = value;                    }                }                item.TextChanged += (object sender, TextChangedEventArgs e) =>                {                    dfLayout.ChangeField(dfLayoutIntegerField.Name);                };                view = item;            }            else if (element is DFLayoutDoubleField)            {                DFLayoutDoubleField dfLayoutDoubleField = element as DFLayoutDoubleField;                item.TextColor = Color.Black;                item.Placeholder = "Enter number";                item.Keyboard = Keyboard.Numeric;                isrequired = dfLayoutDoubleField.Properties.Required;                issecure = dfLayoutDoubleField.Properties.Secure;                if (loadData.TryGetValue(dfLayoutDoubleField.Name, out value))                {                    item.Text = value;                }                if (loadRetainedForm)                {                    if (RetainedResults.Results.TryGetValue(dfLayoutDoubleField.Name, out value))                    {                        item.Text = value;                    }                }                item.TextChanged += (object sender, TextChangedEventArgs e) =>                {                    dfLayout.ChangeField(dfLayoutDoubleField.Name);                };                view = item;            }            if (isrequired) view.BackgroundColor = isRequiredColor;            if (readOnly || issecure)            {                Label label = new Label();                label.Text = item.Text;                label.FontSize = Device.GetNamedSize(NamedSize.Medium, item);                label.TextColor = Color.DarkGray;                label.LineBreakMode = LineBreakMode.WordWrap;                label.MaxLines = 5;                label.VerticalTextAlignment = TextAlignment.Center;                label.HorizontalTextAlignment = TextAlignment.Center;                label.MinimumHeightRequest = 60;                label.VerticalOptions = LayoutOptions.FillAndExpand;                label.Margin = 9;                view = label;            }            return new Tuple<View, Boolean>(view, isrequired);        }        private Tuple<View, Boolean> LoadDatePicker(View view, DFLayoutControl element, string value)        {            DFLayoutDateField dfLayoutDateField = element as DFLayoutDateField;            DatePicker item = new DatePicker();            item.Format = "dd MMM yyyy";            if (dfLayoutDateField.Properties.Required)                item.BackgroundColor = isRequiredColor;            item.HorizontalOptions = LayoutOptions.CenterAndExpand;            if (loadData.TryGetValue(dfLayoutDateField.Name, out value))            {                item.Date = DateTime.Parse(value);            }            if (loadRetainedForm)            {                if (RetainedResults.Results.TryGetValue(dfLayoutDateField.Name, out value))                {                    item.Date = DateTime.Parse(value);                }            }            item.DateSelected += (object sender, DateChangedEventArgs e) =>            {                dfLayout.ChangeField(dfLayoutDateField.Name);            };            view = item;            return new Tuple<View, Boolean>(view, dfLayoutDateField.Properties.Required);        }        private Tuple<View, Boolean> LoadTimePicker(View view, DFLayoutControl element, string value)        {            DFLayoutTimeField dfLayoutTimeField = element as DFLayoutTimeField;            TimePicker item = new TimePicker();            if (dfLayoutTimeField.Properties.Required)                item.BackgroundColor = isRequiredColor;            item.HorizontalOptions = LayoutOptions.Center;            if (loadData.TryGetValue(dfLayoutTimeField.Name, out value))            {                item.Time = DateTime.Parse(value).TimeOfDay;            }            if (loadRetainedForm)            {                if (RetainedResults.Results.TryGetValue(dfLayoutTimeField.Name, out value))                {                    item.Time = DateTime.Parse(value).TimeOfDay;                }            }            item.PropertyChanged += (object sender, System.ComponentModel.PropertyChangedEventArgs e) =>            {                if (e.PropertyName == "Time")                    dfLayout.ChangeField(dfLayoutTimeField.Name);            };            view = item;            return new Tuple<View, Boolean>(view, dfLayoutTimeField.Properties.Required);        }        private Tuple<View, Boolean> LoadOptionPicker(View view, DFLayoutControl element, string value)        {            var isrequired = false;            DFLayoutOptionField dfLayoutOptionField = element as DFLayoutOptionField;            isrequired = dfLayoutOptionField.Properties.Required;            if (GlobalVariables.DeviceString == "i" || GlobalVariables.DeviceString == "I")            {                CustomPickeriOS item = new CustomPickeriOS();                string s = dfLayoutOptionField.Properties.Options;                string[] substrings = s.Split(',');                var optionList = substrings.ToList();                item.AddItems(optionList);                if (!string.IsNullOrEmpty(dfLayoutOptionField.Properties.Default))                {                    int index = optionList.IndexOf(dfLayoutOptionField.Properties.Default);                    item.SelectedIndex = index;                    item.SelectedItem = optionList[index];                    item.SetDefault(optionList[index]);                }                if (loadData.TryGetValue(dfLayoutOptionField.Name, out value))                {                    int index = optionList.IndexOf(value);                    item.SelectedIndex = index;                    item.SelectedItem = optionList[index];                    item.SetDefault(optionList[index]);                }                if (loadRetainedForm)                {                    if (RetainedResults.Results.TryGetValue(dfLayoutOptionField.Name, out value))                    {                        int index = optionList.IndexOf(value);                        item.SelectedIndex = index;                        item.SelectedItem = optionList[index];                        item.SetDefault(optionList[index]);                    }                }                if (isrequired)                {                    item.BackgroundColor = isRequiredColor;                    item.SetBackGroundColor(isRequiredColor);                }                item.CustomPickeriOSValueChanged += () =>                {                    dfLayout.ChangeField(dfLayoutOptionField.Name);                };                view = item;            }            else            {                Picker picker = new Picker();                picker.Title = "Select an option";                picker.VerticalTextAlignment = TextAlignment.Center;                picker.HorizontalTextAlignment = TextAlignment.Center;                string s = dfLayoutOptionField.Properties.Options;                string[] substrings = s.Split(',');                var optionList = substrings.ToList();                picker.ItemsSource = optionList;                if (!string.IsNullOrEmpty(dfLayoutOptionField.Properties.Default))                {                    int index = optionList.IndexOf(dfLayoutOptionField.Properties.Default);                    picker.SelectedIndex = index;                    picker.SelectedItem = optionList[index];                }                if (loadData.TryGetValue(dfLayoutOptionField.Name, out value))                {                    int index = optionList.IndexOf(value);                    picker.SelectedIndex = index;                    picker.SelectedItem = optionList[index];                }                if (loadRetainedForm)                {                    if (RetainedResults.Results.TryGetValue(dfLayoutOptionField.Name, out value))                    {                        int index = optionList.IndexOf(value);                        picker.SelectedIndex = index;                        picker.SelectedItem = optionList[index];                    }                }                if (isrequired)                {                    picker.BackgroundColor = isRequiredColor;                }                picker.SelectedIndexChanged += (object sender, EventArgs e) =>                {                    dfLayout.ChangeField(dfLayoutOptionField.Name);                };                view = picker;            }            return new Tuple<View, Boolean>(view, isrequired);        }        private Tuple<View, Boolean> LoadImage(View view, DFLayoutControl element)        {            DFLayoutImage dfLayoutImage = element as DFLayoutImage;            Image img = new Image();            CoreTable table = new Client<Document>().Query(                    new Filter<Document>(x => x.ID).IsEqualTo(dfLayoutImage.Image.ID),                    null,                    null);            if (table.Rows.Any())            {                CoreRow row = table.Rows.FirstOrDefault();                byte[] data = row.Get<Document, byte[]>(x => x.Data);                ImageSource src = ImageSource.FromStream(() => new MemoryStream(data));                img.MinimumHeightRequest = 150;                img.MinimumWidthRequest = 150;                img.Aspect = Aspect.AspectFit;                img.Source = src;                img.HorizontalOptions = LayoutOptions.FillAndExpand;                img.VerticalOptions = LayoutOptions.FillAndExpand;                img.GestureRecognizers.Add(new TapGestureRecognizer                {                    Command = new Command(OnTap),                    CommandParameter = src,                    NumberOfTapsRequired = 1                });                if (img != null)                {                    view = img;                }            }            return new Tuple<View, Boolean>(view, false);        }        private void OnTap(object obj)        {            ImageViewer viewer = new ImageViewer(obj as ImageSource);            Navigation.PushAsync(viewer);        }        private Tuple<View, Boolean> LoadLookupPicker(View view, DFLayoutControl element, string value)        {            DFLayoutLookupField dfLayoutLookupField = element as DFLayoutLookupField;            var isrequired = dfLayoutLookupField.Properties.Required;            Dictionary<Guid, string> lookupFieldOptions = new Dictionary<Guid, string>();            string type = dfLayoutLookupField.Properties.LookupType;            Type lookuptype = CoreUtils.GetEntityOrNull(type);            if (lookuptype == typeof(DrawingTemplate))                view = LoadDrawingTemplateLookupButton(lookuptype, dfLayoutLookupField, lookupFieldOptions, element);            else if (!string.IsNullOrWhiteSpace(dfLayoutLookupField.Properties.Filter))                view = LoadGenericLookupButton(lookuptype, dfLayoutLookupField, lookupFieldOptions, element);            else if (lookuptype == typeof(Product))                view = LoadProductLookupPicker(view, dfLayoutLookupField, value);            else if (lookuptype != null)                view = LoadGenericLookupButton(lookuptype, dfLayoutLookupField, lookupFieldOptions, element);            else if (lookuptype == null)                view = new Label { Text = "Null lookup selected", HorizontalOptions = LayoutOptions.Center, HorizontalTextAlignment = TextAlignment.Center };            return new Tuple<View, Boolean>(view, isrequired);        }        private View LoadGenericLookupButton(Type lookuptype, DFLayoutLookupField dfLayoutLookupField, Dictionary<Guid, string> lookupFieldOptions, DFLayoutControl element)        {            string value = "";            CoreTable table = new CoreTable();            var client = ClientFactory.CreateClient(lookuptype);            var columns = LookupFactory.DefineColumns(lookuptype);            var sort = LookupFactory.DefineSort(lookuptype);            var filter = LookupFactory.DefineFilter(lookuptype);            foreach (var property in dfLayoutLookupField.Properties.AdditionalPropertiesList)            {                columns.Add(property);            }            if (!string.IsNullOrWhiteSpace(dfLayoutLookupField.Properties.Filter))                filter = ReturnFilter(dfLayoutLookupField, lookuptype);            if (lookuptype == typeof(ProductStyle) && JobID != Guid.Empty)                table = ReturnJobStyleProducts(table, client, columns, sort);            if (table.Rows.Count == 0)                table = client.Query(filter, columns, sort); // do generic query if a specific one hasn't already been done            Dictionary<Guid, Dictionary<string, object>> additionalPropertyValues = new Dictionary<Guid, Dictionary<string, object>>();            foreach (var row in table.Rows)            {                Guid id = row.Get<Guid>("ID");                Dictionary<string, object> values = row.ToDictionary(new string[] { "ID" });                additionalPropertyValues.Add(id, values);                string display = LookupFactory.FormatLookup(lookuptype, values, new string[] { });                lookupFieldOptions[id] = display;            }            dfLayoutLookupFieldLookupOptions[element as DFLayoutLookupField] = lookupFieldOptions;            List<string> itemList = lookupFieldOptions.Values.ToList();            DataButtonControl button = new DataButtonControl()            {                Text = "Choose Option",                HorizontalOptions = LayoutOptions.FillAndExpand,                VerticalOptions = LayoutOptions.Center,                Margin = 0,                BackgroundColor = Color.FromHex("#15C7C1"),                FontAttributes = FontAttributes.Bold,                TextColor = Color.White,                CornerRadius = 5,                Padding = 1,                ExtraData = additionalPropertyValues,                LookupFieldOptions = lookupFieldOptions            };            button.Clicked += (object sender, EventArgs eventArgs) =>            {                ListSelectionPage selectionPage = new ListSelectionPage(lookupFieldOptions);                selectionPage.OnSimpleListTapped += (s) =>                {                    button.Data = s;                    button.Text = s;                    dfLayout.ChangeField(dfLayoutLookupField.Name);                };                selectionPage.OnDictionaryItemTapped += (id, s) =>                {                    button.Data = s;                    button.Text = s;                    button.ChosenID = id;                    dfLayout.ChangeField(dfLayoutLookupField.Name);                };                Navigation.PushAsync(selectionPage);            };            if (loadData.TryGetValue(dfLayoutLookupField.Name, out value))            {                button.Data = value;                button.Text = value;            }            if (loadRetainedForm)            {                if (RetainedResults.Results.TryGetValue(dfLayoutLookupField.Name, out value))                {                    button.Data = value;                    button.Text = value;                }            }            if (isRequired)            {                button.BackgroundColor = isRequiredColor;            }            return button;        }        private View LoadDrawingTemplateLookupButton(Type lookuptype, DFLayoutLookupField dfLayoutLookupField, Dictionary<Guid, string> lookupFieldOptions, DFLayoutControl element)        {            string value = "";            var columns = new Columns<DrawingTemplate>(x => x.Code, x => x.Document.ID);            CoreTable table = new Client<DrawingTemplate>().Query(null, columns);            Dictionary<string, Guid> dictionary = new Dictionary<string, Guid>();            foreach (var row in table.Rows)            {                List<object> list = row.Values;                if (list[0] != null && list[1] != null)                    dictionary.Add(list[0].ToString(), Guid.Parse(list[1].ToString()));            }            DataButtonControl button = new DataButtonControl()            {                Text = "Choose Option",                HorizontalOptions = LayoutOptions.FillAndExpand,                VerticalOptions = LayoutOptions.Center,                Margin = 0,                BackgroundColor = Color.FromHex("#15C7C1"),                FontAttributes = FontAttributes.Bold,                TextColor = Color.White,                CornerRadius = 5,                Padding = 1,            };            button.Clicked += (object sender, EventArgs eventArgs) =>            {                ListSelectionPage selectionPage = new ListSelectionPage(dictionary);                selectionPage.OnSimpleListTapped += (s) =>                {                    button.Data = s;                    button.Text = s;                    dfLayout.ChangeField(dfLayoutLookupField.Name);                };                Navigation.PushAsync(selectionPage);            };            if (loadData.TryGetValue(dfLayoutLookupField.Name, out value))            {                button.Data = value;                button.Text = value;            }            if (loadRetainedForm)            {                if (RetainedResults.Results.TryGetValue(dfLayoutLookupField.Name, out value))                {                    button.Data = value;                    button.Text = value;                }            }            if (isRequired)            {                button.BackgroundColor = isRequiredColor;            }            return button;        }        private IFilter ReturnFilter(DFLayoutLookupField dfLayoutLookupField, Type lookuptype)        {            var propertyFilter = dfLayoutLookupField.Properties.Filter;            var filtertype = typeof(Filter<>).MakeGenericType(lookuptype);            var deserialised = Serialization.Deserialize(filtertype, propertyFilter);            IFilter filter = deserialised as IFilter;            return filter;        }        private CoreTable ReturnJobStyleProducts(CoreTable table, IClient client, IColumns columns, ISortOrder sort)        {            CoreTable jobStyleTable = new Client<JobStyle>().Query(new Filter<JobStyle>(x => x.Job.ID).IsEqualTo(JobID),                    new Columns<JobStyle>(x => x.Style.ID));            if (jobStyleTable.Rows.Any())            {                Guid firstID = Guid.Parse(jobStyleTable.Rows.FirstOrDefault().Values[0].ToString());                var stylefilter = new Filter<ProductStyle>(x => x.ID).IsEqualTo(firstID);                foreach (CoreRow jobStyleRow in jobStyleTable.Rows)                {                    if (jobStyleRow != jobStyleTable.Rows.FirstOrDefault())                    {                        stylefilter = stylefilter.Or(x => x.ID).IsEqualTo(Guid.Parse(jobStyleRow.Values[0].ToString()));                    }                }                table = client.Query(stylefilter, columns, sort);            }            return table;        }        private View LoadProductLookupPicker(View view, DFLayoutLookupField dfLayoutLookupField, string value)        {            FrameButton framebutton = new FrameButton();            if (loadData.TryGetValue(dfLayoutLookupField.Name, out value))            {                framebutton.SetButtonText(value);                framebutton.Data = value + "," + (GlobalVariables.ProductShells.FirstOrDefault(x => x.Code == value)).ID.ToString();                //CoreTable productTable = new Client<Product>().Query(new Filter<Product>(x => x.Code).IsEqualTo(value),                //    new Columns<Product>(x => x.Image.ID));                //if (productTable.Rows.Any())                //{                //    CoreTable imageTable1 = new Client<Document>().Query(new Filter<Document>(x => x.ID).IsEqualTo(Guid.Parse(productTable.Rows.First().Values[0].ToString())),                //            new Columns<Document>(x => x.Data));                //    CoreRow docrow = imageTable1.Rows.FirstOrDefault();                //    if (docrow != null)                //    {                //        byte[] data = docrow.Get<Document, byte[]>(x => x.Data);                //        ImageSource src = ImageSource.FromStream(() => new MemoryStream(data));                //        if (src != null)                //        {                //            framebutton.SetImage(src);                //        }                //    }                //}            }            framebutton.OnFrameButtonClicked += (() =>            {                ProductList productList = new ProductList(GlobalVariables.ProductShells, true);                productList.OnProductSelected += () =>                {                    framebutton.SetButtonText(productList.SelectedProduct.Code);                    framebutton.Data = productList.SelectedProduct.Code + "," + productList.SelectedProduct.ID.ToString();                    //CoreTable imageTable = new Client<Document>().Query(new Filter<Document>(x => x.ID).IsEqualTo(productList.SelectedProduct.ImageID),                    //    new Columns<Document>(x => x.Data));                    //CoreRow docrow = imageTable.Rows.FirstOrDefault();                    //if (docrow != null)                    //{                    //    byte[] data = docrow.Get<Document, byte[]>(x => x.Data);                    //    ImageSource src = ImageSource.FromStream(() => new MemoryStream(data));                    //    if (src != null)                    //    {                    //        framebutton.SetImage(src);                    //    }                    //}                    dfLayout.ChangeField(dfLayoutLookupField.Name);                };                Navigation.PushAsync(productList);            });            view = framebutton;            return view;        }        private Tuple<View, Boolean> LoadSignaturePad(View view, DFLayoutControl element, string value)        {            DFLayoutSignaturePad dFLayoutSignaturePad = element as DFLayoutSignaturePad;            var isrequired = dFLayoutSignaturePad.Properties.Required;            if (loadData.TryGetValue(dFLayoutSignaturePad.Name, out value))            {                EmbeddedImageCapture embeddedImageCapture = new EmbeddedImageCapture();                byte[] data = Convert.FromBase64String(value);                embeddedImageCapture.DataToImage(data);                view = embeddedImageCapture;                view.IsEnabled = false;            }            else            {                SfSignaturePad signaturePad = new SfSignaturePad();                EmbeddedImageCapture hiddenEmbeddedImageCapture = new EmbeddedImageCapture() { HeightRequest = 200, IsVisible = false, IsEnabled = false };                if (isrequired) signaturePad.BackgroundColor = isRequiredColor;                signaturePad.MinimumHeightRequest = 200;                signaturePad.MinimumStrokeWidth = 0.2;                signaturePad.MaximumStrokeWidth = 17;                Button clearButton = new Button()                {                    Text = "Clear",                    HorizontalOptions = LayoutOptions.FillAndExpand,                    VerticalOptions = LayoutOptions.End,                    Margin = 0,                    BackgroundColor = Color.FromHex("#15C7C1"),                    FontAttributes = FontAttributes.Bold,                    TextColor = Color.White,                    CornerRadius = 5,                    Padding = 1                };                clearButton.Clicked += (object sender, EventArgs e) =>                {                    signaturePad.IsVisible = true;                    hiddenEmbeddedImageCapture.IsVisible = false;                    useSavedSignatures.Remove(dFLayoutSignaturePad.Name);                    signaturePad.Clear();                };                Grid.SetColumn(clearButton, 2);                Button signNowButton = new Button()                {                    Text = "Apply Saved",                    HorizontalOptions = LayoutOptions.FillAndExpand,                    VerticalOptions = LayoutOptions.End,                    Margin = 0,                    BackgroundColor = Color.FromHex("#15C7C1"),                    FontAttributes = FontAttributes.Bold,                    TextColor = Color.White,                    CornerRadius = 5,                    Padding = 1                };                signNowButton.Clicked += (object sender, EventArgs e) =>                {                    if (Application.Current.Properties.ContainsKey("SavedSignature"))                    {                        Task.Run(() =>                        {                            hiddenEmbeddedImageCapture.DataToImage((Application.Current.Properties["SavedSignature"]) as byte[]);                        });                        Thread.Sleep(1000);                        signaturePad.IsVisible = false;                        hiddenEmbeddedImageCapture.IsVisible = true;                        if (!useSavedSignatures.Contains(dFLayoutSignaturePad.Name))                            useSavedSignatures.Add(dFLayoutSignaturePad.Name);                    }                };                Grid.SetColumn(signNowButton, 1);                Button createSignatureButton = new Button()                {                    Text = "Save New",                    HorizontalOptions = LayoutOptions.FillAndExpand,                    VerticalOptions = LayoutOptions.End,                    Margin = 0,                    BackgroundColor = Color.FromHex("#15C7C1"),                    FontAttributes = FontAttributes.Bold,                    TextColor = Color.White,                    CornerRadius = 5,                    Padding = 1                };                createSignatureButton.Clicked += (object sender, EventArgs e) =>                {                    SignatureSaver saver = new SignatureSaver();                    saver.OnSignatureSaved += () =>                    {                        Task.Run(() =>                        {                            hiddenEmbeddedImageCapture.DataToImage((Application.Current.Properties["SavedSignature"]) as byte[]);                        });                        Thread.Sleep(1000);                        signaturePad.IsVisible = false;                        hiddenEmbeddedImageCapture.IsVisible = true;                        if (!useSavedSignatures.Contains(dFLayoutSignaturePad.Name))                            useSavedSignatures.Add(dFLayoutSignaturePad.Name);                    };                    Navigation.PushAsync(saver);                };                Grid.SetColumn(createSignatureButton, 0);                Grid buttonsGrid = new Grid { Margin = 0, Padding = 0, VerticalOptions = LayoutOptions.End };                buttonsGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });                buttonsGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });                buttonsGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });                buttonsGrid.Children.Add(createSignatureButton);                buttonsGrid.Children.Add(signNowButton);                buttonsGrid.Children.Add(clearButton);                Grid grid = new Grid() { Margin = 0, Padding = 0 };                grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(200, GridUnitType.Absolute) });                Grid.SetRow(signaturePad, 0);                Grid.SetRow(hiddenEmbeddedImageCapture, 0);                grid.Children.Add(hiddenEmbeddedImageCapture);                grid.Children.Add(signaturePad);                grid.Children.Add(buttonsGrid);                view = grid;            }            return new Tuple<View, Boolean>(view, isrequired);        }        private Tuple<View, Boolean> LoadEmbeddedImage(View view, DFLayoutControl element, string value)        {            bool disableLibrary = false;            DFLayoutEmbeddedImage dfLayoutEmbeddedImage = element as DFLayoutEmbeddedImage;            try            {                disableLibrary = dfLayoutEmbeddedImage.Properties.DisableLibrary;            }            catch { }            EmbeddedImageCapture embeddedImageCapture = new EmbeddedImageCapture(disableLibrary);            if (disableLibrary)                embeddedImageCapture.LibraryButton.BackgroundColor = Color.LightGray;            if (loadData.TryGetValue(dfLayoutEmbeddedImage.Name, out value))            {                byte[] data = Convert.FromBase64String(value);                embeddedImageCapture.DataToImage(data);            }            else            {                if (dfLayoutEmbeddedImage.Properties.Required)                {                    embeddedImageCapture.CameraButton.BackgroundColor = isRequiredColor;                    embeddedImageCapture.CameraButton.BorderWidth = 1;                    embeddedImageCapture.CameraButton.BorderColor = Color.Black;                    if (!disableLibrary)                    {                        embeddedImageCapture.LibraryButton.BackgroundColor = isRequiredColor;                        embeddedImageCapture.LibraryButton.BorderWidth = 1;                        embeddedImageCapture.LibraryButton.BorderColor = Color.Black;                    }                }            }            view = embeddedImageCapture;            return new Tuple<View, Boolean>(view, dfLayoutEmbeddedImage.Properties.Required);        }        private Tuple<View, Boolean> LoadMultiImage(View view, DFLayoutControl element, string value)        {            bool disableLibrary = false;            DFLayoutMultiImage dfLayoutMultiEmbeddedImage = element as DFLayoutMultiImage;            try            {                disableLibrary = dfLayoutMultiEmbeddedImage.Properties.DisableLibrary;            }            catch { }            MultiImageCapture multiImageCapture = new MultiImageCapture(disableLibrary);            if (loadData.TryGetValue(dfLayoutMultiEmbeddedImage.Name, out value))            {                List<string> values = Serialization.Deserialize<List<string>>(value);                foreach (string s in values)                {                    byte[] data = Convert.FromBase64String(s);                    multiImageCapture.DataToImage(data);                }            }            view = multiImageCapture;            return new Tuple<View, bool>(view, dfLayoutMultiEmbeddedImage.Properties.Required);        }        private Tuple<View, bool> LoadMultiSignaturePad(View view, DFLayoutControl element, string value)        {            DFLayoutMultiSignaturePad dfLayoutMultiSignaturePad = element as DFLayoutMultiSignaturePad;            DataButtonControl button = new DataButtonControl            {                Text = "Add Signatures",                TextColor = Color.White,                HorizontalOptions = LayoutOptions.FillAndExpand,                CornerRadius = 0,                BackgroundColor = Color.FromHex("#15C7C1"),                FontAttributes = FontAttributes.Bold            };            if (loadData.TryGetValue(dfLayoutMultiSignaturePad.Name, out value))            {                button.Data = value;            }            MultiSignaturePad multiSignaturePad = new MultiSignaturePad(button.Data);            multiSignaturePad.OnMultiSignatureSaved += (result) =>            {                button.Data = result;            };            button.Clicked += (object sender, EventArgs e) =>            {                Navigation.PushAsync(multiSignaturePad);            };            view = button;            return new Tuple<View, bool>(view, dfLayoutMultiSignaturePad.Properties.Required);        }        private Tuple<View, bool> LoadAddTaskField(View view, DFLayoutControl element, string value)        {            DFLayoutAddTaskField field = element as DFLayoutAddTaskField;            DFCreateTaskView taskView = new DFCreateTaskView();            taskView.OnAddTaskButtonClicked += () =>            {                AddEditTask addEditTask = new AddEditTask(Guid.Empty, "New task from Digital Form");                if (field.Properties.TaskType != null)                {                    addEditTask.kanban.Type.ID = field.Properties.TaskType.ID;                    try                    {                        addEditTask.kanban.Type.Description = new Client<KanbanType>().Query                        (new Filter<KanbanType>(x => x.ID).IsEqualTo(field.Properties.TaskType.ID),                        new Columns<KanbanType>(x => x.Description)).Rows.FirstOrDefault().Values[0].ToString();                    }                    catch { }                    addEditTask.UpdateScreen(true);                }                addEditTask.OnTaskSaved += (taskNumber) =>                {                    taskView.DisableButton();                    taskView.TaskNumber = taskNumber.ToString();                };                Navigation.PushAsync(addEditTask);            };            if (loadData.TryGetValue(field.Name, out value))            {                taskView.TaskNumber = value;                taskView.DisableButton();            }            return new Tuple<View, bool>(taskView, field.Properties.Required);        }        private void FormatAndAddView(View view, DFLayoutControl element, bool isrequired)        {            try            {                if (element is DFLayoutField)                {                    pairs[element as DFLayoutField] = view;                    if (isSecure || readOnly || !string.IsNullOrWhiteSpace((element as DFLayoutField).GetPropertyValue<string>("Expression")))                        view.IsEnabled = false;                    Frame frame = new Frame                    {                        Content = view,                        BorderColor = Color.FromHex("#15C7C1"),                        BackgroundColor = Color.Default,                        CornerRadius = 5,                        Padding = 2,                        HasShadow = false,                    };                    if (readOnly || isSecure)                    {                        frame.BorderColor = Color.Gray;                        frame.BackgroundColor = Color.LightGray;                        frame.VerticalOptions = LayoutOptions.FillAndExpand;                        frame.MinimumHeightRequest = 60;                    }                    if (isrequired)                    {                        frame.BackgroundColor = isRequiredColor;                    }                    view = frame;                }                if (element.Row > 0) SetRow(view, element.Row - 1); //rows and columns coming in from the desktop designer start from 1, not 0 (most of the time??)                else if (element.Row == 0) SetRow(view, dfLayout.RowHeights.Count + 1);                if (element.RowSpan > 0) SetRowSpan(view, element.RowSpan);                else if (element.RowSpan == 0) SetRowSpan(view, 1);                if (element.Column > 0) SetColumn(view, element.Column - 1); //rows and columns coming in from the desktop designer start from 1, not 0 (most of the time??)                if (element.ColumnSpan > 0) SetColumnSpan(view, element.ColumnSpan);                if (element.ColumnSpan > 1)                {                    view.HorizontalOptions = LayoutOptions.FillAndExpand;                    if (view is Label)                    {                        view.HorizontalOptions = LayoutOptions.CenterAndExpand;                        Label lblView = view as Label;                        lblView.HorizontalTextAlignment = TextAlignment.Center;                        view = lblView;                    }                }                else if (element.ColumnSpan == 0) SetColumnSpan(view, 1);                view.SetValue(Grid.MarginProperty, 0.01);                if (element is DFLayoutSignaturePad)                {                    view.Margin = new Thickness(25, 0, 25, 0);                }                Device.BeginInvokeOnMainThread(() => { Children.Add(view); });                if (element is DFLayoutHeader)                    if ((element as DFLayoutHeader).Collapsed)                        headersToCollapse.Add(view as DigitalFormsHeader);            }            catch            { }        }        #endregion        #region Save         public void SaveData(bool saveForLater)        {            try            {                results.Clear();                propertyResults.Clear();                isRequiredEmpty = false;                isRequiredMessage = "";                foreach (DFLayoutField field in pairs.Keys)                {                    View view = pairs[field];                    String userInput = AddResultsToDictionary(field, view);                    if (isRequiredEmpty)                    {                        if (!saveForLater)                            return;                    }                    AddPropertyToDictionary(field, userInput);                }                UpdateInstanceAndModel(saveForLater);            }            catch (Exception ex)            {                errors.Add(ex.Message);            }        }        #region Adding Results to dictionaries        private string AddResultsToDictionary(DFLayoutField field, View view, bool AddToDictionary = true) //"results" dictionary is the data to be saved in Form.Data        {            string userInput = "";            if (field is DFLayoutStringField || field is DFLayoutIntegerField || field is DFLayoutDoubleField)            {                userInput = (view as Editor).Text;            }            else if (field is DFLayoutBooleanField)            {                if ((view as CustomBoolean).ValueChanged)                {                    userInput = (view as CustomBoolean).Value.ToString();                }            }            else if (field is DFLayoutDateField)            {                userInput = ((view as DatePicker).Date).ToString("dd-MM-yyyy");            }            else if (field is DFLayoutTimeField)            {                userInput = ((view as TimePicker).Time).ToString("c");            }            else if (field is DFLayoutOptionField)            {                userInput = GetStringFromOptionField(view);            }            else if (field is DFLayoutLookupField)            {                if (view is DataButtonControl)                {                    var button = view as DataButtonControl;                    userInput = FindIDForDesignLookupField(button); //userinput is used to set guid later on for properties, but will not get added to form data only for lookupfields                                 results.Add(field.Name, button.Data);                    if (RetainedResults.IsFormRetained)                        if ((field as DFLayoutLookupField).Properties.Retain)                            RetainedResults.Results.Add(field.Name, button.Data);                }                else if (view is FrameButton) //currently only used for Products - we already have the Product.ID in Framebutton.Data (saved as Code,ID)                {                    FrameButton framebutton = view as FrameButton;                    if (!string.IsNullOrWhiteSpace(framebutton.Data))                    {                        string[] buttonData = framebutton.Data.Split(',');                        if (AddToDictionary)                            results.Add(field.Name, buttonData[0]); //[0] is product.code                        userInput = buttonData[1]; //[1] is product id as string                        if (RetainedResults.IsFormRetained)                            if ((field as DFLayoutLookupField).Properties.Retain)                                RetainedResults.Results.Add(field.Name, buttonData[0]);                    }                }            }            else if (field is DFLayoutSignaturePad)            {                string value = "";                var grid = view as Grid;                var signaturePad = grid.Children.OfType<SfSignaturePad>().FirstOrDefault();                DFLayoutSignaturePad dFLayoutSignaturePad = field as DFLayoutSignaturePad;                if (loadData.TryGetValue(dFLayoutSignaturePad.Name, out value))                {                    userInput = value;                }                else                {                    if (useSavedSignatures.Contains(dFLayoutSignaturePad.Name))                    {                        ImageSource src = ImageSource.FromStream(() => new MemoryStream((Application.Current.Properties["SavedSignature"]) as byte[]));                        userInput = ImageSourceToBase64(src);                    }                    else                    {                        signaturePad.Save();                        if (signaturePad.ImageSource != null)                        {                            userInput = ImageSourceToBase64(signaturePad.ImageSource);                        }                    }                }            }            else if (field is DFLayoutEmbeddedImage)            {                var embeddedImage = view as EmbeddedImageCapture;                if (embeddedImage.Image.Source != null)                {                    try                    {                        userInput = ImageSourceToBase64(embeddedImage.Image.Source);                    }                    catch (Exception e)                    {                        userInput = "";                    }                }            }            else if (field is DFLayoutMultiImage)            {                var multiImage = view as MultiImageCapture;                if (multiImage.Images.Count > 0)                {                    try                    {                        userInput = ImagesToBase64(multiImage.Images);                    }                    catch (Exception e)                    {                        userInput = "";                    }                }            }            else if (field is DFLayoutAddTaskField)            {                var addTaskButton = view as DFCreateTaskView;                if (!string.IsNullOrWhiteSpace(addTaskButton.TaskNumber))                {                    userInput = addTaskButton.TaskNumber;                }            }            else if (field is DFLayoutMultiSignaturePad)            {                var databutton = view as DataButtonControl;                if (!string.IsNullOrWhiteSpace(databutton.Data))                    userInput = databutton.Data;            }            //add the field name and input to 'results' dictionary for processing outside of QAFormViewer            if (!String.IsNullOrWhiteSpace(userInput) && AddToDictionary)            {                if (field is DFLayoutLookupField)                { /*do nothing as results have already been added*/ }                else                {                    try                    {                        results.Add(field.Name, userInput);                    }                    catch (Exception e)                    {                        errors.Add(e.Message);                    }                    if (RetainedResults.IsFormRetained)                    {                        AddRetainedToDictionary(field, userInput);                    }                }            }            else CheckRequired(field);            return userInput;        }        private void AddPropertyToDictionary(DFLayoutField field, String userInput)        {            if (!string.IsNullOrWhiteSpace(userInput))            {                try                {                    string property = "";                    if (field is DFLayoutStringField)                        property = (field as DFLayoutStringField).Properties.Property;                    else if (field is DFLayoutIntegerField)                        property = (field as DFLayoutIntegerField).Properties.Property;                    else if (field is DFLayoutDoubleField)                        property = (field as DFLayoutDoubleField).Properties.Property;                    else if (field is DFLayoutBooleanField)                        property = (field as DFLayoutBooleanField).Properties.Property;                    else if (field is DFLayoutDateField)                        property = (field as DFLayoutDateField).Properties.Property;                    else if (field is DFLayoutTimeField)                        property = (field as DFLayoutTimeField).Properties.Property;                    else if (field is DFLayoutOptionField)                        property = (field as DFLayoutOptionField).Properties.Property;                    else if (field is DFLayoutLookupField)                        property = (field as DFLayoutLookupField).Properties.Property;                    //'propertyResults' dictionary for processing outside of QAFormViewer                    if (!string.IsNullOrWhiteSpace(property)) propertyResults.Add(property, userInput);                }                catch (Exception e)                {                    errors.Add(e.Message);                    return;                }            }        }        private async void AddRetainedToDictionary(DFLayoutField field, string userInput)        {            await Task.Run(() =>            {                try                {                    if (field is DFLayoutStringField)                    {                        if ((field as DFLayoutStringField).Properties.Retain)                            RetainedResults.Results.Add(field.Name, userInput);                    }                    else if (field is DFLayoutIntegerField)                    {                        if ((field as DFLayoutIntegerField).Properties.Retain)                            RetainedResults.Results.Add(field.Name, userInput);                    }                    else if (field is DFLayoutDoubleField)                    {                        if ((field as DFLayoutDoubleField).Properties.Retain)                            RetainedResults.Results.Add(field.Name, userInput);                    }                    else if (field is DFLayoutBooleanField)                    {                        if ((field as DFLayoutBooleanField).Properties.Retain)                            RetainedResults.Results.Add(field.Name, userInput);                    }                    else if (field is DFLayoutDateField)                    {                        if ((field as DFLayoutDateField).Properties.Retain)                            RetainedResults.Results.Add(field.Name, userInput);                    }                    else if (field is DFLayoutTimeField)                    {                        if ((field as DFLayoutTimeField).Properties.Retain)                            RetainedResults.Results.Add(field.Name, userInput);                    }                    else if (field is DFLayoutOptionField)                    {                        if ((field as DFLayoutOptionField).Properties.Retain)                            RetainedResults.Results.Add(field.Name, userInput);                    }                }                catch (Exception e)                {                    errors.Add("Retained results error: " + e.Message);                }            });        }        #endregion        #region Checks / Custom methods        private void CheckRequired(DFLayoutField field)        {            if (field is DFLayoutStringField)            {                if ((field as DFLayoutStringField).Properties.Required)                {                    isRequiredEmpty = true;                    isRequiredMessage = (field as DFLayoutStringField).Description;                }            }            else if (field is DFLayoutIntegerField)            {                if ((field as DFLayoutIntegerField).Properties.Required)                {                    isRequiredEmpty = true;                    isRequiredMessage = (field as DFLayoutIntegerField).Description;                }            }            else if (field is DFLayoutDoubleField)            {                if ((field as DFLayoutDoubleField).Properties.Required)                {                    {                        isRequiredEmpty = true;                        isRequiredMessage = (field as DFLayoutIntegerField).Description;                    }                }            }            else if (field is DFLayoutBooleanField)            {                if ((field as DFLayoutBooleanField).Properties.Required)                {                    {                        isRequiredEmpty = true;                        isRequiredMessage = (field as DFLayoutBooleanField).Description;                    }                }            }            else if (field is DFLayoutDateField)            {                if ((field as DFLayoutDateField).Properties.Required)                {                    {                        isRequiredEmpty = true;                        isRequiredMessage = (field as DFLayoutDateField).Description;                    }                }            }            else if (field is DFLayoutTimeField)            {                if ((field as DFLayoutTimeField).Properties.Required)                {                    {                        isRequiredEmpty = true;                        isRequiredMessage = (field as DFLayoutTimeField).Description;                    }                }            }            else if (field is DFLayoutOptionField)            {                if ((field as DFLayoutOptionField).Properties.Required)                {                    {                        isRequiredEmpty = true;                        isRequiredMessage = (field as DFLayoutOptionField).Description;                    }                }            }            else if (field is DFLayoutLookupField)            {                if ((field as DFLayoutLookupField).Properties.Required)                {                    {                        isRequiredEmpty = true;                        isRequiredMessage = (field as DFLayoutLookupField).Description;                    }                }            }            else if (field is DFLayoutSignaturePad)            {                if ((field as DFLayoutSignaturePad).Properties.Required)                {                    {                        isRequiredEmpty = true;                        isRequiredMessage = (field as DFLayoutSignaturePad).Description;                    }                }            }            else if (field is DFLayoutEmbeddedImage)            {                if ((field as DFLayoutEmbeddedImage).Properties.Required)                {                    {                        isRequiredEmpty = true;                        isRequiredMessage = (field as DFLayoutEmbeddedImage).Description;                    }                }            }            else if (field is DFLayoutMultiImage)            {                if ((field as DFLayoutMultiImage).Properties.Required)                {                    {                        isRequiredEmpty = true;                        isRequiredMessage = (field as DFLayoutMultiImage).Description;                    }                }            }            else if (field is DFLayoutMultiSignaturePad)            {                if ((field as DFLayoutMultiSignaturePad).Properties.Required)                {                    {                        isRequiredEmpty = true;                        isRequiredMessage = (field as DFLayoutMultiSignaturePad).Description;                    }                }            }        }        private string ImagesToBase64(List<Image> images)        {            List<string> strings = new List<string>();            foreach (Image image in images)            {                strings.Add(ImageSourceToBase64(image.Source));            }            return Serialization.Serialize(strings);        }        private string ImageSourceToBase64(ImageSource source)        {            StreamImageSource streamImageSource = (StreamImageSource)source;            System.Threading.CancellationToken cancellationToken = System.Threading.CancellationToken.None;            Task<Stream> task = streamImageSource.Stream(cancellationToken);            Stream stream = task.Result;            byte[] bytes = new byte[stream.Length];            stream.Read(bytes, 0, bytes.Length);            string s = Convert.ToBase64String(bytes, Base64FormattingOptions.InsertLineBreaks);            return s;        }        private string FindIDForDesignLookupField(DataButtonControl button)        {            try            {                string userInputValue = button.Data;                string guidString = "";                if (userInputValue != nullOrInvalidType)                {                    foreach (KeyValuePair<DFLayoutLookupField, Dictionary<Guid, string>> pair in dfLayoutLookupFieldLookupOptions)                    {                        foreach (KeyValuePair<Guid, string> innerPair in pair.Value)                        {                            if (innerPair.Value == userInputValue)                            {                                guidString = innerPair.Key.ToString();                            }                        }                    }                }                return guidString;            }            catch            {                return "";            }        }        #endregion        #region Save Completion        //point of determination for whether or not QA form gets completed or saved for later        private void UpdateInstanceAndModel(bool saveForLater)        {            if (results.Count != 0)            {                if (!saveForLater)                {                    CompleteForm();                }                model.Instance.FormCompletedBy.ID = userID;                if (digitalFormID != Guid.Empty) model.Instance.Form.ID = digitalFormID;                DigitalForm.SerializeFormData(model.Instance, QueryVariables(model.Instance), results.ToDictionary(x => x.Key, x => x.Value as object));                FormData = model.Instance.FormData;                if (model.Instance.FormStarted == DateTime.MinValue)                {                    model.Instance.FormStarted = timeStarted;                }                TimeSpan span = DateTime.Now - timeStarted;                model.Instance.FormOpen = model.Instance.FormOpen + span;                model.Update(null);            }        }        public List<DigitalFormVariable> QueryVariables(IDigitalFormInstance form)        {            List<DigitalFormVariable> variables = new List<DigitalFormVariable>();            var table = new Client<DigitalFormVariable>().Query(                    new Filter<DigitalFormVariable>(x => x.Form.ID).IsEqualTo(form.Form.ID),                    new Columns<DigitalFormVariable>(x => x.Code, x => x.Parameters, x => x.Description, x => x.VariableType),                    null                    );            foreach (CoreRow coreRow in table.Rows)            {                var variable = coreRow.ToObject<DigitalFormVariable>();                variables.Add(variable);            }            return variables;        }        private void CompleteForm()        {            model.Instance.FormCompleted = DateTime.Now;            FormCompleted = model.Instance.FormCompleted;            model.Instance.Location.Longitude = location.Longitude;            model.Instance.Location.Latitude = location.Latitude;            model.Instance.Location.Timestamp = model.Instance.FormCompleted;        }        #endregion        #endregion        #region Expressions        public object GetFieldValue(string field)        {            try            {                Tuple<DFLayoutField, View> tuple = FindView(field);                return GetValueFromView(tuple.Item1, tuple.Item2);            }            catch            {                return "";            }        }        public void SetFieldValue(string field, object value)        {            try            {                Tuple<DFLayoutField, View> tuple = FindView(field);                SetValueOfView(tuple.Item1, tuple.Item2, value);            }            catch { }        }        public void SetFieldColour(string field, System.Drawing.Color? colour = null)        {            // Not Yet Implemented - over to you, Nick!        }        private void SetValueOfView(DFLayoutField field, View view, object value)        {            if (field is DFLayoutBooleanField)                (view as CustomBoolean).Value = (bool)value;            else if (field is DFLayoutStringField || field is DFLayoutIntegerField || field is DFLayoutDoubleField)                (view as Editor).Text = value.ToString();            else if (field is DFLayoutDateField)                (view as DatePicker).Date = (DateTime)(value as DateTime?);            else if (field is DFLayoutDateTimeField)                (view as TimePicker).Time = (TimeSpan)(value as TimeSpan?);            else if (field is DFLayoutOptionField)                AssignPickerOption(view, field as DFLayoutOptionField, value as string);            else if (field is DFLayoutLookupField)                AssignLookupOption(view, value as string);            else if (field is DFLayoutEmbeddedImage)                AssignImage(view, value as byte[]);        }        private void AssignImage(View view, byte[] bytes)        {            var imageCapture = view as EmbeddedImageCapture;            imageCapture.DataToImage(bytes);        }        private void AssignLookupOption(View view, string value)        {            if (view is DataButtonControl)            {                (view as DataButtonControl).Text = value;                (view as DataButtonControl).Data = value;            }            else if (view is FrameButton) //currently only used for Products - we already have the Product.ID in Framebutton.Data (saved as Code,ID)            {                (view as FrameButton).SetButtonText(value);                (view as FrameButton).Data = value + "," + Guid.Empty.ToString();            }        }        private Tuple<DFLayoutField, View> FindView(string field)        {            DFLayoutField dflayoutfield = pairs.Keys.FirstOrDefault(x => x.Name == field);            View view = pairs[dflayoutfield];            return new Tuple<DFLayoutField, View>(dflayoutfield, view);        }        private void AssignPickerOption(View view, DFLayoutOptionField field, string value)        {            string s = field.Properties.Options;            string[] substrings = s.Split(',');            var optionList = substrings.ToList();            if (GlobalVariables.DeviceString == "i" || GlobalVariables.DeviceString == "I")            {                var iOSPicker = view as CustomPickeriOS;                iOSPicker.SelectedIndex = optionList.IndexOf(value);            }            else            {                var picker = view as Picker;                picker.SelectedIndex = optionList.IndexOf(value);            }        }        private object GetValueFromView(DFLayoutField field, View view)        {            if (field is DFLayoutBooleanField)                return (view as CustomBoolean).Value;            if (field is DFLayoutStringField)                return (view as Editor).Text;            else if (field is DFLayoutIntegerField)                return int.Parse((view as Editor).Text);            else if (field is DFLayoutDoubleField)                return double.Parse((view as Editor).Text);            else if (field is DFLayoutDateField)                return (view as DatePicker).Date;            else if (field is DFLayoutDateTimeField)                return (view as TimePicker).Time;            else if (field is DFLayoutOptionField)                return GetStringFromOptionField(view);            else if (field is DFLayoutLookupField)                return GetStringFromLookupField(view);            else if (field is DFLayoutSignaturePad)                return GetByteArrayFromSignaturePad(view, field.Name);            else if (field is DFLayoutEmbeddedImage)                return GetByteArrayFromEmbeddedImage(view);            else if (field is DFLayoutMultiImage)                return GetByteArrayListFromMultiImage(view);            else return "";        }        private object GetByteArrayListFromMultiImage(View view)        {            List<byte[]> list = new List<byte[]>();            var multiImage = view as MultiImageCapture;            if (multiImage.Images.Count > 0)            {                foreach (Image image in multiImage.Images)                {                    string base64 = ImageSourceToBase64(image.Source);                    list.Add(Convert.FromBase64String(base64));                }            }            return list;        }        private object GetByteArrayFromEmbeddedImage(View view)        {            var embeddedImage = view as EmbeddedImageCapture;            if (embeddedImage.Image.Source != null)            {                string base64 = ImageSourceToBase64(embeddedImage.Image.Source);                return Convert.FromBase64String(base64);            }            else                return null;        }        private byte[] GetByteArrayFromSignaturePad(View view, string name)        {            var grid = view as Grid;            var signaturePad = grid.Children.OfType<SfSignaturePad>().FirstOrDefault();            if (useSavedSignatures.Contains(name))            {                return Application.Current.Properties["SavedSignature"] as byte[];            }            else            {                signaturePad.Save();                if (signaturePad.ImageSource != null)                {                    string base64 = ImageSourceToBase64(signaturePad.ImageSource);                    return Convert.FromBase64String(base64);                }                else                    return null;            }        }        private object GetStringFromLookupField(View view)        {            string value = "";            if (view is DataButtonControl)            {                var button = view as DataButtonControl;                value = FindIDForDesignLookupField(button); //userinput is used to set guid later on for properties, but will not get added to form data only for lookupfields                                                      }            else if (view is FrameButton) //currently only used for Products - we already have the Product.ID in Framebutton.Data (saved as Code,ID)            {                FrameButton framebutton = view as FrameButton;                if (!string.IsNullOrWhiteSpace(framebutton.Data))                {                    string[] buttonData = framebutton.Data.Split(',');                    value = buttonData[1]; //[1] is product id as string                }            }            return value;        }        private string GetStringFromOptionField(View view)        {            if (GlobalVariables.DeviceString == "i" || GlobalVariables.DeviceString == "I")            {                var iOSPicker = view as CustomPickeriOS;                if (iOSPicker.SelectedIndex != -1)                {                    return iOSPicker.SelectedItem.ToString();                }                else                    return "";            }            else            {                var picker = view as Picker;                if (picker.SelectedIndex != -1)                {                    return picker.SelectedItem.ToString();                }                else                    return "";            }        }        public object GetFieldData(string fieldName, string dataField)        {            Tuple<DFLayoutField, View> tuple = FindView(fieldName);            try            {                if (tuple.Item1 is DFLayoutLookupField)                {                    DFLayoutLookupField field = tuple.Item1 as DFLayoutLookupField;                    string type = field.Properties.LookupType;                    Type lookuptype = CoreUtils.GetEntityOrNull(type);                    if (lookuptype == typeof(Product))                    {                        var framebutton = tuple.Item2 as FrameButton;                        string[] buttonData = framebutton.Data.Split(',');                        string id = buttonData[1]; //[1] is product id as string                        CoreTable table = new Client<Product>().Query(new Filter<Product>(x => x.ID).IsEqualTo(Guid.Parse(id)), new Columns<Product>(x => x.Image.ID));                        if (table.Rows.Any())                        {                            Guid returnid = table.Rows.FirstOrDefault().Get<Product, Guid>(x => x.Image.ID);                            return returnid;                        }                        else                            return null;                    }                    else                    {                        var button = tuple.Item2 as DataButtonControl;                        Dictionary<string, object> dict = button.ExtraData[button.ChosenID];                        return dict[dataField];                    }                }                else                    return null;            }            catch            {                return null;            }        }        public void SetFieldColour(string field, System.Drawing.Color? colour = null)        {                    }        #endregion                    }}
 |