QAFormViewer.cs 91 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Threading.Tasks;
  4. using System.Threading;
  5. using System.Linq;
  6. using Xamarin.Forms;
  7. using XF.Material.Forms.UI.Dialogs;
  8. using InABox.Core;
  9. using InABox.Clients;
  10. using System.IO;
  11. using InABox.Mobile;
  12. using Syncfusion.XForms.SignaturePad;
  13. using comal.timesheets.Tasks;
  14. using Comal.Classes;
  15. using PRSClasses;
  16. using IDigitalFormInstance = InABox.Core.IDigitalFormInstance;
  17. namespace comal.timesheets.QAForms
  18. {
  19. public class QAFormViewer : Grid, IDFRenderer
  20. {
  21. #region Fields
  22. public Dictionary<DFLayoutField, View> pairs = new Dictionary<DFLayoutField, View>();
  23. public Dictionary<String, String> results = new Dictionary<String, String>();
  24. public Dictionary<String, String> propertyResults = new Dictionary<String, String>();
  25. Dictionary<String, String> loadData = new Dictionary<String, String>();
  26. public Dictionary<DFLayoutLookupField, Dictionary<Guid, string>> dfLayoutLookupFieldLookupOptions = new Dictionary<DFLayoutLookupField, Dictionary<Guid, string>>();
  27. DFLayout dfLayout = null;
  28. public IDigitalFormDataModel model = null;
  29. const string nullOrInvalidType = "Null or Invalid Type";
  30. int rbGroup;
  31. private Guid userID;
  32. bool isRequired = false;
  33. bool readOnly = false;
  34. bool isSecure = false;
  35. bool loadRetainedForm = false;
  36. List<string> useSavedSignatures = new List<string>();
  37. public List<string> errors = new List<string>();
  38. public bool isRequiredEmpty { get; set; }
  39. public string isRequiredMessage { get; set; }
  40. InABox.Core.Location location = new InABox.Core.Location();
  41. Guid digitalFormID = Guid.Empty;
  42. Color isRequiredColor = Color.DarkOrange;
  43. public string FormData = "";
  44. public DateTime FormCompleted = DateTime.MinValue;
  45. public Guid JobID = Guid.Empty;
  46. DateTime timeStarted = DateTime.MinValue;
  47. List<DigitalFormsHeader> headersToCollapse = new List<DigitalFormsHeader>();
  48. int collapsedHeaderCount = 1;
  49. #endregion
  50. #region Constructor
  51. public QAFormViewer(IDigitalFormDataModel _model, DFLayout _dfLayout, bool newForm, bool _readOnly, Guid _jobid = default(Guid))
  52. {
  53. GetLocation();
  54. timeStarted = DateTime.Now;
  55. userID = ClientFactory.UserGuid;
  56. model = _model;
  57. dfLayout = _dfLayout;
  58. dfLayout.Renderer = this;
  59. readOnly = _readOnly;
  60. isRequiredEmpty = false;
  61. loadRetainedForm = false;
  62. isRequiredMessage = "";
  63. JobID = _jobid;
  64. if (RetainedResults.IsFormRetained)
  65. {
  66. loadRetainedForm = true;
  67. }
  68. if (newForm)
  69. {
  70. LoadForm();
  71. }
  72. else if (!newForm)
  73. {
  74. loadData.Clear();
  75. Dictionary<String, Object> data = DigitalForm.DeserializeFormData(model.Instance);
  76. if (data != null)
  77. {
  78. foreach (KeyValuePair<string, object> keyValuePair in data)
  79. {
  80. loadData.Add(keyValuePair.Key, keyValuePair.Value.ToString());
  81. }
  82. }
  83. LoadForm();
  84. }
  85. }
  86. #endregion
  87. #region Location
  88. private async void GetLocation()
  89. {
  90. await Task.Run(() =>
  91. {
  92. LocationServices locationServices = new LocationServices();
  93. locationServices.OnLocationFound += LocationFound;
  94. locationServices.OnLocationError += LocationError;
  95. locationServices.GetLocation();
  96. });
  97. }
  98. private async void LocationFound(LocationServices sender)
  99. {
  100. location.Latitude = sender.Latitude;
  101. location.Longitude = sender.Longitude;
  102. }
  103. private async void LocationError(LocationServices sender, Exception error)
  104. {
  105. errors.Add("Location error: " + error.Message);
  106. }
  107. #endregion Location
  108. #region Load Form Layout
  109. private async void LoadForm()
  110. {
  111. {
  112. LoadRowsAndColumns();
  113. LoadElements();
  114. }
  115. }
  116. private void LoadRowsAndColumns()
  117. {
  118. LoadRows();
  119. LoadColumns();
  120. }
  121. private void LoadRows()
  122. {
  123. foreach (var row in dfLayout.RowHeights)
  124. {
  125. RowDefinition def = new RowDefinition { Height = new GridLength(1, GridUnitType.Auto) };
  126. if (int.TryParse(row, out int rowHeight))
  127. {
  128. def = new RowDefinition { Height = new GridLength(rowHeight, GridUnitType.Absolute) };
  129. if (def.Height.Value < 60)
  130. {
  131. def.SetValue(RowDefinition.HeightProperty, 60);
  132. }
  133. }
  134. else if (row.Contains("*"))
  135. {
  136. if (int.TryParse(row.Substring(0, row.IndexOf("*")), out int result))
  137. {
  138. def = new RowDefinition { Height = new GridLength(result, GridUnitType.Star) };
  139. }
  140. else
  141. def = new RowDefinition { Height = new GridLength(1, GridUnitType.Star) };
  142. }
  143. Device.BeginInvokeOnMainThread(() => { RowDefinitions.Add(def); });
  144. }
  145. }
  146. private void LoadColumns()
  147. {
  148. foreach (var col in dfLayout.ColumnWidths)
  149. {
  150. ColumnDefinition def = new ColumnDefinition { Width = new GridLength(1, GridUnitType.Auto) };
  151. if (int.TryParse(col, out int colWidth))
  152. def = new ColumnDefinition { Width = new GridLength(colWidth, GridUnitType.Absolute) };
  153. else if (col.Contains("*"))
  154. {
  155. if (int.TryParse(col.Substring(0, col.IndexOf("*")), out int result))
  156. {
  157. def = new ColumnDefinition { Width = new GridLength(result, GridUnitType.Star) };
  158. }
  159. else
  160. def = new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) };
  161. }
  162. Device.BeginInvokeOnMainThread(() => { ColumnDefinitions.Add(def); });
  163. }
  164. }
  165. private void LoadElements()
  166. {
  167. rbGroup = 0; //used for customboolean - has to be outside of foreach loop
  168. foreach (DFLayoutControl element in dfLayout.Elements)
  169. {
  170. if (!string.IsNullOrEmpty(element.Description))
  171. {
  172. LoadViewAccordingToElement(element);
  173. }
  174. }
  175. Task.Run(() =>
  176. {
  177. Thread.Sleep(1000);
  178. foreach (var header in headersToCollapse)
  179. {
  180. Device.BeginInvokeOnMainThread(() =>
  181. {
  182. AdjustHeaderSection(header, false);
  183. header.Collapse();
  184. });
  185. }
  186. });
  187. }
  188. #endregion
  189. #region Load Element Methods
  190. private void LoadViewAccordingToElement(DFLayoutControl element)
  191. {
  192. isSecure = false;
  193. if (element is DFLayoutBooleanField)
  194. {
  195. var tuple = LoadCustomBoolean(element);
  196. FormatAndAddView(tuple.Item1, element, tuple.Item2);
  197. }
  198. else if (element is DFLayoutLabel)
  199. {
  200. var tuple = LoadLabel(element);
  201. FormatAndAddView(tuple.Item1, element, tuple.Item2);
  202. }
  203. else if (element is DFLayoutStringField || element is DFLayoutIntegerField || element is DFLayoutDoubleField)
  204. {
  205. var tuple = LoadEditor(element);
  206. FormatAndAddView(tuple.Item1, element, tuple.Item2);
  207. }
  208. else if (element is DFLayoutDateField)
  209. {
  210. var tuple = LoadDatePicker(element);
  211. FormatAndAddView(tuple.Item1, element, tuple.Item2);
  212. }
  213. else if (element is DFLayoutTimeField)
  214. {
  215. var tuple = LoadTimePicker(element);
  216. FormatAndAddView(tuple.Item1, element, tuple.Item2);
  217. }
  218. else if (element is DFLayoutOptionField)
  219. {
  220. var tuple = LoadOptionPicker(element);
  221. FormatAndAddView(tuple.Item1, element, tuple.Item2);
  222. }
  223. else if (element is DFLayoutImage)
  224. {
  225. var tuple = LoadImage(element);
  226. FormatAndAddView(tuple.Item1, element, tuple.Item2);
  227. }
  228. else if (element is DFLayoutLookupField)
  229. {
  230. var tuple = LoadLookupPicker(element);
  231. FormatAndAddView(tuple.Item1, element, tuple.Item2);
  232. }
  233. else if (element is DFLayoutSignaturePad)
  234. {
  235. var tuple = LoadSignaturePad(element);
  236. FormatAndAddView(tuple.Item1, element, tuple.Item2);
  237. }
  238. else if (element is DFLayoutEmbeddedImage)
  239. {
  240. var tuple = LoadEmbeddedImage(element);
  241. FormatAndAddView(tuple.Item1, element, tuple.Item2);
  242. }
  243. else if (element is DFLayoutMultiImage)
  244. {
  245. var tuple = LoadMultiImage(element);
  246. FormatAndAddView(tuple.Item1, element, tuple.Item2);
  247. }
  248. else if (element is DFLayoutMultiSignaturePad)
  249. {
  250. var tuple = LoadMultiSignaturePad(element);
  251. FormatAndAddView(tuple.Item1, element, tuple.Item2);
  252. }
  253. else if (element is DFLayoutAddTaskField)
  254. {
  255. var tuple = LoadAddTaskField(element);
  256. FormatAndAddView(tuple.Item1, element, tuple.Item2);
  257. }
  258. else if (element is DFLayoutHeader)
  259. {
  260. FormatAndAddView(LoadHeader(element), element, false);
  261. }
  262. else if (element is DFLayoutVideoField)
  263. {
  264. var tuple = LoadVideoField(element);
  265. FormatAndAddView(tuple.Item1, element, tuple.Item2);
  266. }
  267. }
  268. private View LoadHeader(DFLayoutControl element)
  269. {
  270. DFLayoutHeader dFLayoutHeader = (DFLayoutHeader)element;
  271. DigitalFormsHeader header = new DigitalFormsHeader(dFLayoutHeader.Collapsed);
  272. header.SetHeaderStyle(dFLayoutHeader);
  273. if (dFLayoutHeader.Collapsed)
  274. header = AddNumberToHeader(header);
  275. header.SetHeaderValue(dFLayoutHeader.Header);
  276. header.OnTapped += (bCollapsed) =>
  277. {
  278. AdjustHeaderSection(header, bCollapsed);
  279. };
  280. return header;
  281. }
  282. private DigitalFormsHeader AddNumberToHeader(DigitalFormsHeader header)
  283. {
  284. header.Number = collapsedHeaderCount;
  285. collapsedHeaderCount++;
  286. return header;
  287. }
  288. private void AdjustHeaderSection(DigitalFormsHeader header, bool collapsed)
  289. {
  290. try
  291. {
  292. var thisHeaderRow = GetRow(header);
  293. var headerRows = GetOtherHeaders(thisHeaderRow);
  294. if (headerRows.Any())
  295. AdjustHeightsToNextHeader(headerRows, thisHeaderRow, collapsed);
  296. else
  297. AdjustHeightsBelowHeader(headerRows, thisHeaderRow, collapsed);
  298. }
  299. catch
  300. {
  301. }
  302. }
  303. private List<int> GetOtherHeaders(int thisHeaderRow)
  304. {
  305. List<int> headerRows = new List<int>();
  306. foreach (var child in Children)
  307. {
  308. if (child is DigitalFormsHeader)
  309. {
  310. var dfheader = (DigitalFormsHeader)child;
  311. if (GetRow(dfheader) > thisHeaderRow)
  312. {
  313. headerRows.Add(GetRow(dfheader));
  314. }
  315. }
  316. }
  317. return headerRows;
  318. }
  319. private void AdjustHeightsToNextHeader(List<int> headerRows, int thisHeaderRow, bool collapsed)
  320. {
  321. headerRows.Sort();
  322. int nextHeaderRow = headerRows[0];
  323. for (int i = thisHeaderRow + 1; i < nextHeaderRow; i++)
  324. {
  325. AdjustHeight(i, collapsed);
  326. }
  327. }
  328. private void AdjustHeightsBelowHeader(List<int> headerRows, int thisHeaderRow, bool collapsed)
  329. {
  330. for (int i = thisHeaderRow + 1; i < RowDefinitions.Count; i++)
  331. {
  332. AdjustHeight(i, collapsed);
  333. }
  334. }
  335. private void AdjustHeight(int i, bool collapsed)
  336. {
  337. var rowdef = RowDefinitions[i];
  338. if (collapsed)
  339. {
  340. rowdef.Height = 60;
  341. //AnimateChildren(i, 0, 250);
  342. }
  343. else
  344. {
  345. //AnimateChildren(i, -60, 500);
  346. rowdef.Height = 0;
  347. }
  348. }
  349. private async void AnimateChildren(int i, int movement, int length)
  350. {
  351. foreach (var child in Children)
  352. {
  353. if (GetRow(child) == i)
  354. {
  355. await child.TranslateTo(0, movement, 250);
  356. }
  357. }
  358. }
  359. private Tuple<View, Boolean> LoadCustomBoolean(DFLayoutControl element)
  360. {
  361. string value = "";
  362. rbGroup++;
  363. CustomBoolean item = new CustomBoolean(rbGroup);
  364. DFLayoutBooleanField dfLayoutBooleanField = element as DFLayoutBooleanField;
  365. if (!string.IsNullOrWhiteSpace(dfLayoutBooleanField.Properties.TrueValue))
  366. item.trueBtn.Content = dfLayoutBooleanField.Properties.TrueValue;
  367. if (!string.IsNullOrWhiteSpace(dfLayoutBooleanField.Properties.FalseValue))
  368. item.falseBtn.Content = dfLayoutBooleanField.Properties.FalseValue;
  369. if (loadData.TryGetValue(dfLayoutBooleanField.Name, out value))
  370. {
  371. if (!string.IsNullOrWhiteSpace(value))
  372. {
  373. item.Value = bool.Parse(value);
  374. if (bool.Parse(value) == false)
  375. item.SetFalseValue();
  376. }
  377. }
  378. if (loadRetainedForm)
  379. {
  380. if (RetainedResults.Results.TryGetValue(dfLayoutBooleanField.Name, out value))
  381. {
  382. item.Value = bool.Parse(value);
  383. }
  384. }
  385. if (dfLayoutBooleanField.Properties.Required)
  386. {
  387. item.trueBtn.BackgroundColor = isRequiredColor;
  388. item.falseBtn.BackgroundColor = isRequiredColor;
  389. }
  390. item.OnCustomBooleanValueChanged += (boolvalue) =>
  391. {
  392. dfLayout.ChangeField(dfLayoutBooleanField.Name);
  393. };
  394. return new Tuple<View, Boolean>(item, dfLayoutBooleanField.Properties.Required);
  395. }
  396. private Tuple<View, Boolean> LoadLabel(DFLayoutControl element)
  397. {
  398. DFLayoutLabel label = element as DFLayoutLabel;
  399. Label item = new Label();
  400. item.Text = label.Caption;
  401. item.TextColor = Color.Black;
  402. item.LineBreakMode = label.Style.TextWrapping == true ? LineBreakMode.WordWrap : LineBreakMode.NoWrap;
  403. item.VerticalOptions = LayoutOptions.FillAndExpand;
  404. item.MinimumHeightRequest = 60;
  405. item.BackgroundColor = label.Style.BackgroundColour;
  406. item.FontAttributes = label.Style.IsBold ? FontAttributes.Bold
  407. : label.Style.IsItalic ? FontAttributes.Italic
  408. : FontAttributes.None;
  409. item.TextDecorations = label.Style.Underline == UnderlineType.Single || label.Style.Underline == UnderlineType.Double ?
  410. TextDecorations.Underline : TextDecorations.None;
  411. item.FontSize = label.Style.FontSize > 5 && label.Style.FontSize < 37 ? label.Style.FontSize
  412. : Device.GetNamedSize(NamedSize.Medium, item);
  413. item.TextColor = label.Style.ForegroundColour;
  414. if (ColumnDefinitions.Count == 1)
  415. {
  416. item.HorizontalOptions = LayoutOptions.CenterAndExpand;
  417. item.HorizontalTextAlignment = TextAlignment.Center;
  418. }
  419. item.HorizontalTextAlignment = label.Style.HorizontalTextAlignment == DFLayoutAlignment.Start ? TextAlignment.Start
  420. : label.Style.HorizontalTextAlignment == DFLayoutAlignment.Middle ? TextAlignment.Center
  421. : label.Style.HorizontalTextAlignment == DFLayoutAlignment.End ? TextAlignment.End
  422. : item.HorizontalTextAlignment;
  423. item.VerticalTextAlignment = label.Style.VerticalTextAlignment == DFLayoutAlignment.Start ? TextAlignment.Start
  424. : label.Style.HorizontalTextAlignment == DFLayoutAlignment.Middle ? TextAlignment.Center
  425. : label.Style.HorizontalTextAlignment == DFLayoutAlignment.End ? TextAlignment.End
  426. : TextAlignment.Center;
  427. return new Tuple<View, Boolean>(item, false);
  428. }
  429. private Tuple<View, Boolean> LoadEditor(DFLayoutControl element)
  430. {
  431. string value = "";
  432. View view = null;
  433. Editor item = new Editor();
  434. item.AutoSize = EditorAutoSizeOption.TextChanges;
  435. var isrequired = false;
  436. var issecure = false;
  437. if (element is DFLayoutStringField)
  438. {
  439. DFLayoutStringField dfLayoutStringField = element as DFLayoutStringField;
  440. item.TextColor = Color.Black;
  441. item.Placeholder = "Enter answer";
  442. isrequired = dfLayoutStringField.Properties.Required;
  443. issecure = dfLayoutStringField.Properties.Secure;
  444. DataButtonControl button = new DataButtonControl();
  445. button.Clicked += (s, e) =>
  446. {
  447. PopupEditor edt = new PopupEditor(button.Data);
  448. edt.OnPopupEdtSaved += (text) =>
  449. {
  450. button.Data = text;
  451. button.Text = text.Length > 25 ? text.Substring(0, 25) + "..." : text;
  452. dfLayout.ChangeField(dfLayoutStringField.Name);
  453. };
  454. Navigation.PushAsync(edt);
  455. };
  456. button.Text = "Edit";
  457. if (loadData.TryGetValue(dfLayoutStringField.Name, out value))
  458. {
  459. if (!string.IsNullOrWhiteSpace(value))
  460. {
  461. item.Text = value;
  462. button.Text = value.Length > 25 ? value.Substring(0, 25) + "..." : value;
  463. }
  464. }
  465. if (loadRetainedForm)
  466. {
  467. if (RetainedResults.Results.TryGetValue(dfLayoutStringField.Name, out value))
  468. {
  469. item.Text = value;
  470. button.Text = value.Length > 25 ? value.Substring(0, 25) + "..." : value;
  471. }
  472. }
  473. item.TextChanged += (object sender, TextChangedEventArgs e) =>
  474. {
  475. dfLayout.ChangeField(dfLayoutStringField.Name);
  476. };
  477. if (dfLayoutStringField.Properties.PopupEditor)
  478. view = button;
  479. else
  480. view = item;
  481. }
  482. else if (element is DFLayoutIntegerField)
  483. {
  484. DFLayoutIntegerField dfLayoutIntegerField = element as DFLayoutIntegerField;
  485. item.TextColor = Color.Black;
  486. item.Placeholder = "Enter number";
  487. item.Keyboard = Keyboard.Numeric;
  488. isrequired = dfLayoutIntegerField.Properties.Required;
  489. issecure = dfLayoutIntegerField.Properties.Secure;
  490. if (loadData.TryGetValue(dfLayoutIntegerField.Name, out value))
  491. {
  492. if (!string.IsNullOrWhiteSpace(value))
  493. {
  494. item.Text = value;
  495. }
  496. }
  497. if (loadRetainedForm)
  498. {
  499. if (RetainedResults.Results.TryGetValue(dfLayoutIntegerField.Name, out value))
  500. {
  501. item.Text = value;
  502. }
  503. }
  504. item.TextChanged += (object sender, TextChangedEventArgs e) =>
  505. {
  506. dfLayout.ChangeField(dfLayoutIntegerField.Name);
  507. };
  508. view = item;
  509. }
  510. else if (element is DFLayoutDoubleField)
  511. {
  512. DFLayoutDoubleField dfLayoutDoubleField = element as DFLayoutDoubleField;
  513. item.TextColor = Color.Black;
  514. item.Placeholder = "Enter number";
  515. item.Keyboard = Keyboard.Numeric;
  516. isrequired = dfLayoutDoubleField.Properties.Required;
  517. issecure = dfLayoutDoubleField.Properties.Secure;
  518. if (loadData.TryGetValue(dfLayoutDoubleField.Name, out value))
  519. {
  520. if (!string.IsNullOrWhiteSpace(value))
  521. {
  522. item.Text = value;
  523. }
  524. }
  525. if (loadRetainedForm)
  526. {
  527. if (RetainedResults.Results.TryGetValue(dfLayoutDoubleField.Name, out value))
  528. {
  529. item.Text = value;
  530. }
  531. }
  532. item.TextChanged += (object sender, TextChangedEventArgs e) =>
  533. {
  534. dfLayout.ChangeField(dfLayoutDoubleField.Name);
  535. };
  536. view = item;
  537. }
  538. if (isrequired) view.BackgroundColor = isRequiredColor;
  539. if (readOnly || issecure)
  540. {
  541. Label label = new Label();
  542. label.Text = item.Text;
  543. label.FontSize = Device.GetNamedSize(NamedSize.Medium, item);
  544. label.TextColor = Color.DarkGray;
  545. label.LineBreakMode = LineBreakMode.WordWrap;
  546. label.MaxLines = 5;
  547. label.VerticalTextAlignment = TextAlignment.Center;
  548. label.HorizontalTextAlignment = TextAlignment.Center;
  549. label.MinimumHeightRequest = 60;
  550. label.VerticalOptions = LayoutOptions.FillAndExpand;
  551. label.Margin = 9;
  552. view = label;
  553. }
  554. return new Tuple<View, Boolean>(view, isrequired);
  555. }
  556. private Tuple<View, Boolean> LoadDatePicker(DFLayoutControl element)
  557. {
  558. string value = "";
  559. DFLayoutDateField dfLayoutDateField = element as DFLayoutDateField;
  560. DatePicker item = new DatePicker();
  561. item.Format = "dd MMM yyyy";
  562. if (dfLayoutDateField.Properties.Required)
  563. item.BackgroundColor = isRequiredColor;
  564. item.HorizontalOptions = LayoutOptions.CenterAndExpand;
  565. if (loadData.TryGetValue(dfLayoutDateField.Name, out value))
  566. {
  567. if (!string.IsNullOrWhiteSpace(value))
  568. {
  569. item.Date = DateTime.Parse(value);
  570. }
  571. }
  572. if (loadRetainedForm)
  573. {
  574. if (RetainedResults.Results.TryGetValue(dfLayoutDateField.Name, out value))
  575. {
  576. item.Date = DateTime.Parse(value);
  577. }
  578. }
  579. item.DateSelected += (object sender, DateChangedEventArgs e) =>
  580. {
  581. dfLayout.ChangeField(dfLayoutDateField.Name);
  582. };
  583. return new Tuple<View, Boolean>(item, dfLayoutDateField.Properties.Required);
  584. }
  585. private Tuple<View, Boolean> LoadTimePicker(DFLayoutControl element)
  586. {
  587. string value = "";
  588. DFLayoutTimeField dfLayoutTimeField = element as DFLayoutTimeField;
  589. TimePicker item = new TimePicker();
  590. if (dfLayoutTimeField.Properties.Required)
  591. item.BackgroundColor = isRequiredColor;
  592. item.HorizontalOptions = LayoutOptions.Center;
  593. if (loadData.TryGetValue(dfLayoutTimeField.Name, out value))
  594. {
  595. if (!string.IsNullOrWhiteSpace(value))
  596. {
  597. item.Time = DateTime.Parse(value).TimeOfDay;
  598. }
  599. }
  600. if (loadRetainedForm)
  601. {
  602. if (RetainedResults.Results.TryGetValue(dfLayoutTimeField.Name, out value))
  603. {
  604. item.Time = DateTime.Parse(value).TimeOfDay;
  605. }
  606. }
  607. item.PropertyChanged += (object sender, System.ComponentModel.PropertyChangedEventArgs e) =>
  608. {
  609. if (e.PropertyName == "Time")
  610. dfLayout.ChangeField(dfLayoutTimeField.Name);
  611. };
  612. return new Tuple<View, Boolean>(item, dfLayoutTimeField.Properties.Required);
  613. }
  614. private Tuple<View, Boolean> LoadOptionPicker(DFLayoutControl element)
  615. {
  616. View view = null;
  617. try
  618. {
  619. string value = "";
  620. var isrequired = false;
  621. DFLayoutOptionField dfLayoutOptionField = element as DFLayoutOptionField;
  622. isrequired = dfLayoutOptionField.Properties.Required;
  623. if (Device.RuntimePlatform.Equals(Device.iOS))
  624. {
  625. CustomPickeriOS item = new CustomPickeriOS();
  626. string s = dfLayoutOptionField.Properties.Options;
  627. string[] substrings = s.Split(',');
  628. var optionList = substrings.ToList();
  629. item.AddItems(optionList);
  630. if (!string.IsNullOrEmpty(dfLayoutOptionField.Properties.Default))
  631. {
  632. int index = optionList.IndexOf(dfLayoutOptionField.Properties.Default);
  633. item.SelectedIndex = index;
  634. item.SelectedItem = optionList[index];
  635. item.SetDefault(optionList[index]);
  636. }
  637. if (loadData.TryGetValue(dfLayoutOptionField.Name, out value))
  638. {
  639. if (!string.IsNullOrWhiteSpace(value))
  640. {
  641. int index = optionList.IndexOf(value);
  642. item.SelectedIndex = index;
  643. item.SelectedItem = optionList[index];
  644. item.SetDefault(optionList[index]);
  645. }
  646. }
  647. if (loadRetainedForm)
  648. {
  649. if (RetainedResults.Results.TryGetValue(dfLayoutOptionField.Name, out value))
  650. {
  651. int index = optionList.IndexOf(value);
  652. item.SelectedIndex = index;
  653. item.SelectedItem = optionList[index];
  654. item.SetDefault(optionList[index]);
  655. }
  656. }
  657. if (isrequired)
  658. {
  659. item.BackgroundColor = isRequiredColor;
  660. item.SetBackGroundColor(isRequiredColor);
  661. }
  662. item.CustomPickeriOSValueChanged += () =>
  663. {
  664. dfLayout.ChangeField(dfLayoutOptionField.Name);
  665. };
  666. view = item;
  667. }
  668. else
  669. {
  670. Picker picker = new Picker();
  671. picker.Title = "Select an option";
  672. picker.VerticalTextAlignment = TextAlignment.Center;
  673. picker.HorizontalTextAlignment = TextAlignment.Center;
  674. string s = dfLayoutOptionField.Properties.Options;
  675. string[] substrings = s.Split(',');
  676. var optionList = substrings.ToList();
  677. picker.ItemsSource = optionList;
  678. if (!string.IsNullOrEmpty(dfLayoutOptionField.Properties.Default))
  679. {
  680. int index = optionList.IndexOf(dfLayoutOptionField.Properties.Default);
  681. picker.SelectedIndex = index;
  682. picker.SelectedItem = optionList[index];
  683. }
  684. if (loadData.TryGetValue(dfLayoutOptionField.Name, out value))
  685. {
  686. if (!string.IsNullOrWhiteSpace(value))
  687. {
  688. int index = optionList.IndexOf(value);
  689. picker.SelectedIndex = index;
  690. picker.SelectedItem = optionList[index];
  691. }
  692. }
  693. if (loadRetainedForm)
  694. {
  695. if (RetainedResults.Results.TryGetValue(dfLayoutOptionField.Name, out value))
  696. {
  697. int index = optionList.IndexOf(value);
  698. picker.SelectedIndex = index;
  699. picker.SelectedItem = optionList[index];
  700. }
  701. }
  702. if (isrequired)
  703. {
  704. picker.BackgroundColor = isRequiredColor;
  705. }
  706. picker.SelectedIndexChanged += (object sender, EventArgs e) =>
  707. {
  708. dfLayout.ChangeField(dfLayoutOptionField.Name);
  709. };
  710. view = picker;
  711. }
  712. return new Tuple<View, Boolean>(view, isrequired);
  713. }
  714. catch
  715. {
  716. return new Tuple<View, Boolean>(view, false);
  717. }
  718. }
  719. private Tuple<View, Boolean> LoadImage(DFLayoutControl element)
  720. {
  721. View view = null;
  722. DFLayoutImage dfLayoutImage = element as DFLayoutImage;
  723. Image img = new Image();
  724. CoreTable table = new Client<Document>().Query(
  725. new Filter<Document>(x => x.ID).IsEqualTo(dfLayoutImage.Image.ID),
  726. null,
  727. null);
  728. if (table.Rows.Any())
  729. {
  730. CoreRow row = table.Rows.FirstOrDefault();
  731. byte[] data = row.Get<Document, byte[]>(x => x.Data);
  732. ImageSource src = ImageSource.FromStream(() => new MemoryStream(data));
  733. img.MinimumHeightRequest = 150;
  734. img.MinimumWidthRequest = 150;
  735. img.Aspect = Aspect.AspectFit;
  736. img.Source = src;
  737. img.HorizontalOptions = LayoutOptions.FillAndExpand;
  738. img.VerticalOptions = LayoutOptions.FillAndExpand;
  739. img.GestureRecognizers.Add(new TapGestureRecognizer
  740. {
  741. Command = new Command(OnTap),
  742. CommandParameter = src,
  743. NumberOfTapsRequired = 1
  744. });
  745. if (img != null)
  746. {
  747. view = img;
  748. }
  749. }
  750. return new Tuple<View, Boolean>(view, false);
  751. }
  752. private void OnTap(object obj)
  753. {
  754. ImageViewer viewer = new ImageViewer(obj as ImageSource);
  755. Navigation.PushAsync(viewer);
  756. }
  757. private Tuple<View, Boolean> LoadLookupPicker(DFLayoutControl element)
  758. {
  759. View view = null;
  760. string value = "";
  761. DFLayoutLookupField dfLayoutLookupField = element as DFLayoutLookupField;
  762. var isrequired = dfLayoutLookupField.Properties.Required;
  763. Dictionary<Guid, string> lookupFieldOptions = new Dictionary<Guid, string>();
  764. string type = dfLayoutLookupField.Properties.LookupType;
  765. Type lookuptype = CoreUtils.GetEntityOrNull(type);
  766. if (lookuptype == typeof(DrawingTemplate))
  767. view = LoadDrawingTemplateLookupButton(lookuptype, dfLayoutLookupField, lookupFieldOptions, element);
  768. else if (!string.IsNullOrWhiteSpace(dfLayoutLookupField.Properties.Filter))
  769. view = LoadGenericLookupButton(lookuptype, dfLayoutLookupField, lookupFieldOptions, element);
  770. else if (lookuptype == typeof(Product))
  771. view = LoadProductLookupPicker(view, dfLayoutLookupField, value);
  772. else if (lookuptype != null)
  773. view = LoadGenericLookupButton(lookuptype, dfLayoutLookupField, lookupFieldOptions, element);
  774. else if (lookuptype == null)
  775. view = new Label { Text = "Null lookup selected", HorizontalOptions = LayoutOptions.Center, HorizontalTextAlignment = TextAlignment.Center };
  776. return new Tuple<View, Boolean>(view, isrequired);
  777. }
  778. private View LoadGenericLookupButton(Type lookuptype, DFLayoutLookupField dfLayoutLookupField, Dictionary<Guid, string> lookupFieldOptions, DFLayoutControl element)
  779. {
  780. string value = "";
  781. CoreTable table = new CoreTable();
  782. var client = ClientFactory.CreateClient(lookuptype);
  783. var columns = LookupFactory.DefineColumns(lookuptype);
  784. var sort = LookupFactory.DefineSort(lookuptype);
  785. var filter = LookupFactory.DefineFilter(lookuptype);
  786. foreach (var property in dfLayoutLookupField.Properties.AdditionalPropertiesList)
  787. {
  788. columns.Add(property);
  789. }
  790. if (!string.IsNullOrWhiteSpace(dfLayoutLookupField.Properties.Filter))
  791. filter = ReturnFilter(dfLayoutLookupField, lookuptype);
  792. if (lookuptype == typeof(ProductStyle) && JobID != Guid.Empty)
  793. table = ReturnJobStyleProducts(table, client, columns, sort);
  794. if (table.Rows.Count == 0)
  795. table = client.Query(filter, columns, sort); // do generic query if a specific one hasn't already been done
  796. Dictionary<Guid, Dictionary<string, object>> additionalPropertyValues = new Dictionary<Guid, Dictionary<string, object>>();
  797. foreach (var row in table.Rows)
  798. {
  799. Guid id = row.Get<Guid>("ID");
  800. Dictionary<string, object> values = row.ToDictionary(new string[] { "ID" });
  801. additionalPropertyValues.Add(id, values);
  802. string display = LookupFactory.FormatLookup(lookuptype, values, new string[] { });
  803. lookupFieldOptions[id] = display;
  804. }
  805. dfLayoutLookupFieldLookupOptions[element as DFLayoutLookupField] = lookupFieldOptions;
  806. List<string> itemList = lookupFieldOptions.Values.ToList();
  807. DataButtonControl button = new DataButtonControl()
  808. {
  809. Text = "Choose Option",
  810. Margin = 0,
  811. ExtraData = additionalPropertyValues,
  812. LookupFieldOptions = lookupFieldOptions
  813. };
  814. button.Clicked += (object sender, EventArgs eventArgs) =>
  815. {
  816. ListSelectionPage selectionPage = new ListSelectionPage(lookupFieldOptions);
  817. selectionPage.OnSimpleListTapped += (s) =>
  818. {
  819. button.Data = s;
  820. button.Text = s;
  821. dfLayout.ChangeField(dfLayoutLookupField.Name);
  822. };
  823. selectionPage.OnDictionaryItemTapped += (id, s) =>
  824. {
  825. button.Data = s;
  826. button.Text = s;
  827. button.ChosenID = id;
  828. dfLayout.ChangeField(dfLayoutLookupField.Name);
  829. };
  830. Navigation.PushAsync(selectionPage);
  831. };
  832. if (loadData.TryGetValue(dfLayoutLookupField.Name, out value))
  833. {
  834. if (!string.IsNullOrWhiteSpace(value))
  835. {
  836. button.Data = value;
  837. button.Text = value;
  838. }
  839. }
  840. if (loadRetainedForm)
  841. {
  842. if (RetainedResults.Results.TryGetValue(dfLayoutLookupField.Name, out value))
  843. {
  844. button.Data = value;
  845. button.Text = value;
  846. }
  847. }
  848. if (isRequired)
  849. {
  850. button.BackgroundColor = isRequiredColor;
  851. }
  852. return button;
  853. }
  854. private View LoadDrawingTemplateLookupButton(Type lookuptype, DFLayoutLookupField dfLayoutLookupField, Dictionary<Guid, string> lookupFieldOptions, DFLayoutControl element)
  855. {
  856. string value = "";
  857. var columns = new Columns<DrawingTemplate>(x => x.Code, x => x.Document.ID);
  858. CoreTable table = new Client<DrawingTemplate>().Query(null, columns);
  859. Dictionary<string, Guid> dictionary = new Dictionary<string, Guid>();
  860. foreach (var row in table.Rows)
  861. {
  862. List<object> list = row.Values;
  863. if (list[0] != null && list[1] != null)
  864. dictionary.Add(list[0].ToString(), Guid.Parse(list[1].ToString()));
  865. }
  866. DataButtonControl button = new DataButtonControl()
  867. {
  868. Text = "Choose Option",
  869. };
  870. button.Clicked += (object sender, EventArgs eventArgs) =>
  871. {
  872. ListSelectionPage selectionPage = new ListSelectionPage(dictionary);
  873. selectionPage.OnSimpleListTapped += (s) =>
  874. {
  875. button.Data = s;
  876. button.Text = s;
  877. dfLayout.ChangeField(dfLayoutLookupField.Name);
  878. };
  879. Navigation.PushAsync(selectionPage);
  880. };
  881. if (loadData.TryGetValue(dfLayoutLookupField.Name, out value))
  882. {
  883. if (!string.IsNullOrWhiteSpace(value))
  884. {
  885. button.Data = value;
  886. button.Text = value;
  887. }
  888. }
  889. if (loadRetainedForm)
  890. {
  891. if (RetainedResults.Results.TryGetValue(dfLayoutLookupField.Name, out value))
  892. {
  893. button.Data = value;
  894. button.Text = value;
  895. }
  896. }
  897. if (isRequired)
  898. {
  899. button.BackgroundColor = isRequiredColor;
  900. }
  901. return button;
  902. }
  903. private IFilter ReturnFilter(DFLayoutLookupField dfLayoutLookupField, Type lookuptype)
  904. {
  905. var propertyFilter = dfLayoutLookupField.Properties.Filter;
  906. var filtertype = typeof(Filter<>).MakeGenericType(lookuptype);
  907. var deserialised = Serialization.Deserialize(filtertype, propertyFilter);
  908. IFilter filter = deserialised as IFilter;
  909. return filter;
  910. }
  911. private CoreTable ReturnJobStyleProducts(CoreTable table, IClient client, IColumns columns, ISortOrder sort)
  912. {
  913. CoreTable jobStyleTable = new Client<JobStyle>().Query(new Filter<JobStyle>(x => x.Job.ID).IsEqualTo(JobID),
  914. new Columns<JobStyle>(x => x.Style.ID));
  915. if (jobStyleTable.Rows.Any())
  916. {
  917. Guid firstID = Guid.Parse(jobStyleTable.Rows.FirstOrDefault().Values[0].ToString());
  918. var stylefilter = new Filter<ProductStyle>(x => x.ID).IsEqualTo(firstID);
  919. foreach (CoreRow jobStyleRow in jobStyleTable.Rows)
  920. {
  921. if (jobStyleRow != jobStyleTable.Rows.FirstOrDefault())
  922. {
  923. stylefilter = stylefilter.Or(x => x.ID).IsEqualTo(Guid.Parse(jobStyleRow.Values[0].ToString()));
  924. }
  925. }
  926. table = client.Query(stylefilter, columns, sort);
  927. }
  928. return table;
  929. }
  930. private View LoadProductLookupPicker(View view, DFLayoutLookupField dfLayoutLookupField, string value)
  931. {
  932. FrameButton framebutton = new FrameButton();
  933. if (loadData.TryGetValue(dfLayoutLookupField.Name, out value))
  934. {
  935. framebutton.SetButtonText(value);
  936. framebutton.Data = value + "," + (App.Data.Products.Items.FirstOrDefault(x => x.Code == value)).ID.ToString();
  937. //CoreTable productTable = new Client<Product>().Query(new Filter<Product>(x => x.Code).IsEqualTo(value),
  938. // new Columns<Product>(x => x.Image.ID));
  939. //if (productTable.Rows.Any())
  940. //{
  941. // CoreTable imageTable1 = new Client<Document>().Query(new Filter<Document>(x => x.ID).IsEqualTo(Guid.Parse(productTable.Rows.First().Values[0].ToString())),
  942. // new Columns<Document>(x => x.Data));
  943. // CoreRow docrow = imageTable1.Rows.FirstOrDefault();
  944. // if (docrow != null)
  945. // {
  946. // byte[] data = docrow.Get<Document, byte[]>(x => x.Data);
  947. // ImageSource src = ImageSource.FromStream(() => new MemoryStream(data));
  948. // if (src != null)
  949. // {
  950. // framebutton.SetImage(src);
  951. // }
  952. // }
  953. //}
  954. }
  955. framebutton.OnFrameButtonClicked += (() =>
  956. {
  957. ProductList productList = new ProductList(App.Data.Products.Items.ToList(), true);
  958. productList.OnProductSelected += () =>
  959. {
  960. framebutton.SetButtonText(productList.SelectedProduct.Code);
  961. framebutton.Data = productList.SelectedProduct.Code + "," + productList.SelectedProduct.ID.ToString();
  962. //CoreTable imageTable = new Client<Document>().Query(new Filter<Document>(x => x.ID).IsEqualTo(productList.SelectedProduct.ImageID),
  963. // new Columns<Document>(x => x.Data));
  964. //CoreRow docrow = imageTable.Rows.FirstOrDefault();
  965. //if (docrow != null)
  966. //{
  967. // byte[] data = docrow.Get<Document, byte[]>(x => x.Data);
  968. // ImageSource src = ImageSource.FromStream(() => new MemoryStream(data));
  969. // if (src != null)
  970. // {
  971. // framebutton.SetImage(src);
  972. // }
  973. //}
  974. dfLayout.ChangeField(dfLayoutLookupField.Name);
  975. };
  976. Navigation.PushAsync(productList);
  977. });
  978. view = framebutton;
  979. return view;
  980. }
  981. private Tuple<View, Boolean> LoadSignaturePad(DFLayoutControl element)
  982. {
  983. string value = "";
  984. View view = null;
  985. DFLayoutSignaturePad dFLayoutSignaturePad = element as DFLayoutSignaturePad;
  986. var isrequired = dFLayoutSignaturePad.Properties.Required;
  987. if (loadData.TryGetValue(dFLayoutSignaturePad.Name, out value))
  988. {
  989. if (!string.IsNullOrWhiteSpace(value))
  990. {
  991. EmbeddedImageCapture embeddedImageCapture = new EmbeddedImageCapture();
  992. byte[] data = Convert.FromBase64String(value);
  993. embeddedImageCapture.DataToImage(data);
  994. view = embeddedImageCapture;
  995. view.IsEnabled = false;
  996. }
  997. }
  998. else
  999. {
  1000. SfSignaturePad signaturePad = new SfSignaturePad();
  1001. EmbeddedImageCapture hiddenEmbeddedImageCapture = new EmbeddedImageCapture() { HeightRequest = 200, IsVisible = false, IsEnabled = false };
  1002. if (isrequired) signaturePad.BackgroundColor = isRequiredColor;
  1003. signaturePad.MinimumHeightRequest = 200;
  1004. signaturePad.MinimumStrokeWidth = 0.2;
  1005. signaturePad.MaximumStrokeWidth = 17;
  1006. Button clearButton = new Button()
  1007. {
  1008. Text = "Clear",
  1009. HorizontalOptions = LayoutOptions.FillAndExpand,
  1010. VerticalOptions = LayoutOptions.End,
  1011. Margin = 0,
  1012. BackgroundColor = Color.FromHex("#15C7C1"),
  1013. FontAttributes = FontAttributes.Bold,
  1014. TextColor = Color.White,
  1015. CornerRadius = 5,
  1016. Padding = 1
  1017. };
  1018. clearButton.Clicked += (object sender, EventArgs e) =>
  1019. {
  1020. signaturePad.IsVisible = true;
  1021. hiddenEmbeddedImageCapture.IsVisible = false;
  1022. useSavedSignatures.Remove(dFLayoutSignaturePad.Name);
  1023. signaturePad.Clear();
  1024. };
  1025. Grid.SetColumn(clearButton, 2);
  1026. Button signNowButton = new Button()
  1027. {
  1028. Text = "Apply Saved",
  1029. HorizontalOptions = LayoutOptions.FillAndExpand,
  1030. VerticalOptions = LayoutOptions.End,
  1031. Margin = 0,
  1032. BackgroundColor = Color.FromHex("#15C7C1"),
  1033. FontAttributes = FontAttributes.Bold,
  1034. TextColor = Color.White,
  1035. CornerRadius = 5,
  1036. Padding = 1
  1037. };
  1038. signNowButton.Clicked += (object sender, EventArgs e) =>
  1039. {
  1040. if (Application.Current.Properties.ContainsKey("SavedSignature"))
  1041. {
  1042. Task.Run(() =>
  1043. {
  1044. hiddenEmbeddedImageCapture.DataToImage((Application.Current.Properties["SavedSignature"]) as byte[]);
  1045. });
  1046. Thread.Sleep(1000);
  1047. signaturePad.IsVisible = false;
  1048. hiddenEmbeddedImageCapture.IsVisible = true;
  1049. if (!useSavedSignatures.Contains(dFLayoutSignaturePad.Name))
  1050. useSavedSignatures.Add(dFLayoutSignaturePad.Name);
  1051. }
  1052. };
  1053. Grid.SetColumn(signNowButton, 1);
  1054. Button createSignatureButton = new Button()
  1055. {
  1056. Text = "Save New",
  1057. HorizontalOptions = LayoutOptions.FillAndExpand,
  1058. VerticalOptions = LayoutOptions.End,
  1059. Margin = 0,
  1060. BackgroundColor = Color.FromHex("#15C7C1"),
  1061. FontAttributes = FontAttributes.Bold,
  1062. TextColor = Color.White,
  1063. CornerRadius = 5,
  1064. Padding = 1
  1065. };
  1066. createSignatureButton.Clicked += (object sender, EventArgs e) =>
  1067. {
  1068. SignatureSaver saver = new SignatureSaver();
  1069. saver.OnSignatureSaved += () =>
  1070. {
  1071. Task.Run(() =>
  1072. {
  1073. hiddenEmbeddedImageCapture.DataToImage((Application.Current.Properties["SavedSignature"]) as byte[]);
  1074. });
  1075. Thread.Sleep(1000);
  1076. signaturePad.IsVisible = false;
  1077. hiddenEmbeddedImageCapture.IsVisible = true;
  1078. if (!useSavedSignatures.Contains(dFLayoutSignaturePad.Name))
  1079. useSavedSignatures.Add(dFLayoutSignaturePad.Name);
  1080. };
  1081. Navigation.PushAsync(saver);
  1082. };
  1083. Grid.SetColumn(createSignatureButton, 0);
  1084. Grid buttonsGrid = new Grid { Margin = 0, Padding = 0, VerticalOptions = LayoutOptions.End };
  1085. buttonsGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
  1086. buttonsGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
  1087. buttonsGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
  1088. buttonsGrid.Children.Add(createSignatureButton);
  1089. buttonsGrid.Children.Add(signNowButton);
  1090. buttonsGrid.Children.Add(clearButton);
  1091. Grid grid = new Grid() { Margin = 0, Padding = 0 };
  1092. grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(200, GridUnitType.Absolute) });
  1093. Grid.SetRow(signaturePad, 0);
  1094. Grid.SetRow(hiddenEmbeddedImageCapture, 0);
  1095. grid.Children.Add(hiddenEmbeddedImageCapture);
  1096. grid.Children.Add(signaturePad);
  1097. grid.Children.Add(buttonsGrid);
  1098. view = grid;
  1099. }
  1100. return new Tuple<View, Boolean>(view, isrequired);
  1101. }
  1102. private Tuple<View, Boolean> LoadEmbeddedImage(DFLayoutControl element)
  1103. {
  1104. string value = "";
  1105. bool disableLibrary = false;
  1106. DFLayoutEmbeddedImage dfLayoutEmbeddedImage = element as DFLayoutEmbeddedImage;
  1107. try
  1108. {
  1109. disableLibrary = dfLayoutEmbeddedImage.Properties.DisableLibrary;
  1110. }
  1111. catch { }
  1112. EmbeddedImageCapture embeddedImageCapture = new EmbeddedImageCapture(disableLibrary);
  1113. if (disableLibrary)
  1114. embeddedImageCapture.LibraryButton.BackgroundColor = Color.LightGray;
  1115. if (loadData.TryGetValue(dfLayoutEmbeddedImage.Name, out value))
  1116. {
  1117. if (!string.IsNullOrWhiteSpace(value))
  1118. {
  1119. byte[] data = Convert.FromBase64String(value);
  1120. embeddedImageCapture.DataToImage(data);
  1121. }
  1122. }
  1123. else
  1124. {
  1125. if (dfLayoutEmbeddedImage.Properties.Required)
  1126. {
  1127. embeddedImageCapture.CameraButton.BackgroundColor = isRequiredColor;
  1128. embeddedImageCapture.CameraButton.BorderWidth = 1;
  1129. embeddedImageCapture.CameraButton.BorderColor = Color.Black;
  1130. if (!disableLibrary)
  1131. {
  1132. embeddedImageCapture.LibraryButton.BackgroundColor = isRequiredColor;
  1133. embeddedImageCapture.LibraryButton.BorderWidth = 1;
  1134. embeddedImageCapture.LibraryButton.BorderColor = Color.Black;
  1135. }
  1136. }
  1137. }
  1138. return new Tuple<View, Boolean>(embeddedImageCapture, dfLayoutEmbeddedImage.Properties.Required);
  1139. }
  1140. private Tuple<View, Boolean> LoadVideoField(DFLayoutControl element)
  1141. {
  1142. string value = "";
  1143. bool disableLibrary = false;
  1144. DFLayoutVideoField vidField = element as DFLayoutVideoField;
  1145. EmbeddedImageCapture embeddedImageCapture = new EmbeddedImageCapture(false, true);
  1146. embeddedImageCapture.VideoQuality =
  1147. vidField.Properties.Quality == DFLayoutVideoFieldProperties.VideoQuality.Low ? Plugin.Media.Abstractions.VideoQuality.Low :
  1148. vidField.Properties.Quality == DFLayoutVideoFieldProperties.VideoQuality.Medium ? Plugin.Media.Abstractions.VideoQuality.Medium :
  1149. vidField.Properties.Quality == DFLayoutVideoFieldProperties.VideoQuality.High ? Plugin.Media.Abstractions.VideoQuality.High :
  1150. vidField.Properties.Quality == DFLayoutVideoFieldProperties.VideoQuality.Default ? Plugin.Media.Abstractions.VideoQuality.Medium :
  1151. Plugin.Media.Abstractions.VideoQuality.Medium;
  1152. embeddedImageCapture.VideoLength =
  1153. vidField.Properties.MaximumVideoLength == 0 ? new TimeSpan(0, 0, 20) :
  1154. new TimeSpan(0, 0, vidField.Properties.MaximumVideoLength);
  1155. if (loadData.TryGetValue(vidField.Name, out value))
  1156. {
  1157. byte[] data = Convert.FromBase64String(value);
  1158. }
  1159. else
  1160. {
  1161. if (vidField.Properties.Required)
  1162. {
  1163. embeddedImageCapture.CameraButton.BackgroundColor = isRequiredColor;
  1164. embeddedImageCapture.CameraButton.BorderWidth = 1;
  1165. embeddedImageCapture.CameraButton.BorderColor = Color.Black;
  1166. if (!disableLibrary)
  1167. {
  1168. embeddedImageCapture.LibraryButton.BackgroundColor = isRequiredColor;
  1169. embeddedImageCapture.LibraryButton.BorderWidth = 1;
  1170. embeddedImageCapture.LibraryButton.BorderColor = Color.Black;
  1171. }
  1172. }
  1173. }
  1174. return new Tuple<View, Boolean>(embeddedImageCapture, vidField.Properties.Required);
  1175. }
  1176. private Tuple<View, Boolean> LoadMultiImage(DFLayoutControl element)
  1177. {
  1178. string value = "";
  1179. bool disableLibrary = false;
  1180. DFLayoutMultiImage dfLayoutMultiEmbeddedImage = element as DFLayoutMultiImage;
  1181. try
  1182. {
  1183. disableLibrary = dfLayoutMultiEmbeddedImage.Properties.DisableLibrary;
  1184. }
  1185. catch { }
  1186. MultiImageCapture multiImageCapture = new MultiImageCapture(disableLibrary);
  1187. if (loadData.TryGetValue(dfLayoutMultiEmbeddedImage.Name, out value))
  1188. {
  1189. List<string> values = Serialization.Deserialize<List<string>>(value);
  1190. foreach (string s in values)
  1191. {
  1192. byte[] data = Convert.FromBase64String(s);
  1193. multiImageCapture.DataToImage(data);
  1194. }
  1195. }
  1196. return new Tuple<View, bool>(multiImageCapture, dfLayoutMultiEmbeddedImage.Properties.Required);
  1197. }
  1198. private Tuple<View, bool> LoadMultiSignaturePad(DFLayoutControl element)
  1199. {
  1200. string value = "";
  1201. DFLayoutMultiSignaturePad dfLayoutMultiSignaturePad = element as DFLayoutMultiSignaturePad;
  1202. DataButtonControl button = new DataButtonControl
  1203. {
  1204. Text = "Add Signatures",
  1205. };
  1206. if (loadData.TryGetValue(dfLayoutMultiSignaturePad.Name, out value))
  1207. {
  1208. button.Data = value;
  1209. }
  1210. MultiSignaturePad multiSignaturePad = new MultiSignaturePad(button.Data);
  1211. multiSignaturePad.OnMultiSignatureSaved += (result) =>
  1212. {
  1213. button.Data = result;
  1214. };
  1215. button.Clicked += (object sender, EventArgs e) =>
  1216. {
  1217. Navigation.PushAsync(multiSignaturePad);
  1218. };
  1219. return new Tuple<View, bool>(button, dfLayoutMultiSignaturePad.Properties.Required);
  1220. }
  1221. private Tuple<View, bool> LoadAddTaskField(DFLayoutControl element)
  1222. {
  1223. string value = "";
  1224. DFLayoutAddTaskField field = element as DFLayoutAddTaskField;
  1225. DFCreateTaskView taskView = new DFCreateTaskView();
  1226. taskView.OnAddTaskButtonClicked += () =>
  1227. {
  1228. AddEditTask addEditTask = new AddEditTask(Guid.Empty, "New task from Digital Form");
  1229. if (field.Properties.TaskType != null)
  1230. {
  1231. addEditTask.kanban.Type.ID = field.Properties.TaskType.ID;
  1232. try
  1233. {
  1234. addEditTask.kanban.Type.Description = new Client<KanbanType>().Query
  1235. (new Filter<KanbanType>(x => x.ID).IsEqualTo(field.Properties.TaskType.ID),
  1236. new Columns<KanbanType>(x => x.Description)).Rows.FirstOrDefault().Values[0].ToString();
  1237. }
  1238. catch { }
  1239. addEditTask.UpdateScreen(true);
  1240. }
  1241. addEditTask.OnTaskSaved += (taskNumber) =>
  1242. {
  1243. taskView.DisableButton();
  1244. taskView.TaskNumber = taskNumber.ToString();
  1245. };
  1246. Navigation.PushAsync(addEditTask);
  1247. };
  1248. if (loadData.TryGetValue(field.Name, out value))
  1249. {
  1250. taskView.TaskNumber = value;
  1251. taskView.DisableButton();
  1252. }
  1253. return new Tuple<View, bool>(taskView, field.Properties.Required);
  1254. }
  1255. private void FormatAndAddView(View view, DFLayoutControl element, bool isrequired)
  1256. {
  1257. try
  1258. {
  1259. if (element is DFLayoutField)
  1260. {
  1261. pairs[element as DFLayoutField] = view;
  1262. if (isSecure || readOnly || !string.IsNullOrWhiteSpace((element as DFLayoutField).GetPropertyValue<string>("Expression")))
  1263. view.IsEnabled = false;
  1264. Frame frame = new Frame
  1265. {
  1266. Content = view,
  1267. BorderColor = Color.FromHex("#15C7C1"),
  1268. BackgroundColor = Color.Default,
  1269. CornerRadius = 5,
  1270. Padding = 2,
  1271. HasShadow = false,
  1272. };
  1273. if (readOnly || isSecure)
  1274. {
  1275. frame.BorderColor = Color.Gray;
  1276. frame.BackgroundColor = Color.LightGray;
  1277. frame.VerticalOptions = LayoutOptions.FillAndExpand;
  1278. frame.MinimumHeightRequest = 60;
  1279. }
  1280. if (isrequired)
  1281. {
  1282. frame.BackgroundColor = isRequiredColor;
  1283. }
  1284. view = frame;
  1285. }
  1286. if (element.Row > 0)
  1287. SetRow(view, element.Row - 1); //rows and columns coming in from the desktop designer start from 1, not 0 (most of the time??)
  1288. else if (element.Row == 0)
  1289. SetRow(view, dfLayout.RowHeights.Count + 1);
  1290. if (element.RowSpan > 0)
  1291. SetRowSpan(view, element.RowSpan);
  1292. else if (element.RowSpan == 0)
  1293. SetRowSpan(view, 1);
  1294. if (element.Column > 0)
  1295. SetColumn(view, element.Column - 1); //rows and columns coming in from the desktop designer start from 1, not 0 (most of the time??)
  1296. if (element.ColumnSpan > 0)
  1297. SetColumnSpan(view, element.ColumnSpan);
  1298. if (element.ColumnSpan > 1)
  1299. {
  1300. view.HorizontalOptions = LayoutOptions.FillAndExpand;
  1301. if (view is Label)
  1302. {
  1303. view.HorizontalOptions = LayoutOptions.CenterAndExpand;
  1304. Label lblView = view as Label;
  1305. lblView.HorizontalTextAlignment = TextAlignment.Center;
  1306. view = lblView;
  1307. }
  1308. }
  1309. else if (element.ColumnSpan == 0) SetColumnSpan(view, 1);
  1310. view.SetValue(Grid.MarginProperty, 0.01);
  1311. if (element is DFLayoutSignaturePad)
  1312. view.Margin = new Thickness(25, 0, 25, 0);
  1313. Device.BeginInvokeOnMainThread(() =>
  1314. {
  1315. Children.Add(view);
  1316. });
  1317. if (element is DFLayoutHeader)
  1318. if ((element as DFLayoutHeader).Collapsed)
  1319. headersToCollapse.Add(view as DigitalFormsHeader);
  1320. }
  1321. catch
  1322. { }
  1323. }
  1324. #endregion
  1325. #region Save
  1326. public void SaveData(bool saveForLater)
  1327. {
  1328. try
  1329. {
  1330. results.Clear();
  1331. propertyResults.Clear();
  1332. isRequiredEmpty = false;
  1333. isRequiredMessage = "";
  1334. foreach (DFLayoutField field in pairs.Keys)
  1335. {
  1336. View view = pairs[field];
  1337. String userInput = AddResultsToDictionary(field, view);
  1338. if (isRequiredEmpty)
  1339. {
  1340. if (!saveForLater)
  1341. return;
  1342. }
  1343. AddPropertyToDictionary(field, userInput);
  1344. }
  1345. UpdateInstanceAndModel(saveForLater);
  1346. }
  1347. catch (Exception ex)
  1348. {
  1349. }
  1350. }
  1351. #region Adding Results to dictionaries
  1352. private string AddResultsToDictionary(DFLayoutField field, View view, bool AddToDictionary = true) //"results" dictionary is the data to be saved in Form.Data
  1353. {
  1354. string userInput = "";
  1355. if (field is DFLayoutStringField || field is DFLayoutIntegerField || field is DFLayoutDoubleField)
  1356. {
  1357. if (field is DFLayoutStringField && (field as DFLayoutStringField).Properties.PopupEditor)
  1358. userInput = (view as DataButtonControl).Data;
  1359. else
  1360. userInput = (view as Editor).Text;
  1361. }
  1362. else if (field is DFLayoutBooleanField)
  1363. {
  1364. if ((view as CustomBoolean).ValueChanged)
  1365. {
  1366. userInput = (view as CustomBoolean).Value.ToString();
  1367. }
  1368. }
  1369. else if (field is DFLayoutDateField)
  1370. {
  1371. userInput = ((view as DatePicker).Date).ToString("dd-MM-yyyy");
  1372. }
  1373. else if (field is DFLayoutTimeField)
  1374. {
  1375. userInput = ((view as TimePicker).Time).ToString("c");
  1376. }
  1377. else if (field is DFLayoutOptionField)
  1378. {
  1379. userInput = GetStringFromOptionField(view);
  1380. }
  1381. else if (field is DFLayoutLookupField)
  1382. {
  1383. if (view is DataButtonControl)
  1384. {
  1385. var button = view as DataButtonControl;
  1386. userInput = FindIDForDesignLookupField(button); //userinput is used to set guid later on for properties, but will not get added to form data only for lookupfields
  1387. results.Add(field.Name, button.Data);
  1388. if (RetainedResults.IsFormRetained)
  1389. if ((field as DFLayoutLookupField).Properties.Retain)
  1390. RetainedResults.Results.Add(field.Name, button.Data);
  1391. }
  1392. else if (view is FrameButton) //currently only used for Products - we already have the Product.ID in Framebutton.Data (saved as Code,ID)
  1393. {
  1394. FrameButton framebutton = view as FrameButton;
  1395. if (!string.IsNullOrWhiteSpace(framebutton.Data))
  1396. {
  1397. string[] buttonData = framebutton.Data.Split(',');
  1398. if (AddToDictionary)
  1399. results.Add(field.Name, buttonData[0]); //[0] is product.code
  1400. userInput = buttonData[1]; //[1] is product id as string
  1401. if (RetainedResults.IsFormRetained)
  1402. if ((field as DFLayoutLookupField).Properties.Retain)
  1403. RetainedResults.Results.Add(field.Name, buttonData[0]);
  1404. }
  1405. }
  1406. }
  1407. else if (field is DFLayoutSignaturePad)
  1408. {
  1409. string value = "";
  1410. var grid = view as Grid;
  1411. var signaturePad = grid.Children.OfType<SfSignaturePad>().FirstOrDefault();
  1412. DFLayoutSignaturePad dFLayoutSignaturePad = field as DFLayoutSignaturePad;
  1413. if (loadData.TryGetValue(dFLayoutSignaturePad.Name, out value))
  1414. {
  1415. userInput = value;
  1416. }
  1417. else
  1418. {
  1419. if (useSavedSignatures.Contains(dFLayoutSignaturePad.Name))
  1420. {
  1421. ImageSource src = ImageSource.FromStream(() => new MemoryStream((Application.Current.Properties["SavedSignature"]) as byte[]));
  1422. userInput = ImageSourceToBase64(src);
  1423. }
  1424. else
  1425. {
  1426. signaturePad.Save();
  1427. if (signaturePad.ImageSource != null)
  1428. {
  1429. userInput = ImageSourceToBase64(signaturePad.ImageSource);
  1430. }
  1431. }
  1432. }
  1433. }
  1434. else if (field is DFLayoutEmbeddedImage)
  1435. {
  1436. var embeddedImage = view as EmbeddedImageCapture;
  1437. if (embeddedImage.Image.Source != null)
  1438. {
  1439. try
  1440. {
  1441. userInput = ImageSourceToBase64(embeddedImage.Image.Source);
  1442. }
  1443. catch (Exception e)
  1444. {
  1445. userInput = "";
  1446. }
  1447. }
  1448. }
  1449. else if (field is DFLayoutVideoField)
  1450. {
  1451. var embeddedImage = view as EmbeddedImageCapture;
  1452. if (embeddedImage.bytes != null)
  1453. {
  1454. if (embeddedImage.bytes.Length > 0)
  1455. {
  1456. try
  1457. {
  1458. userInput = BytesToBase64(embeddedImage.bytes);
  1459. }
  1460. catch (Exception e)
  1461. {
  1462. userInput = "";
  1463. }
  1464. }
  1465. }
  1466. }
  1467. else if (field is DFLayoutMultiImage)
  1468. {
  1469. var multiImage = view as MultiImageCapture;
  1470. if (multiImage.Images.Count > 0)
  1471. {
  1472. try
  1473. {
  1474. userInput = ImagesToBase64(multiImage.Images);
  1475. }
  1476. catch (Exception e)
  1477. {
  1478. userInput = "";
  1479. }
  1480. }
  1481. }
  1482. else if (field is DFLayoutAddTaskField)
  1483. {
  1484. var addTaskButton = view as DFCreateTaskView;
  1485. if (!string.IsNullOrWhiteSpace(addTaskButton.TaskNumber))
  1486. {
  1487. userInput = addTaskButton.TaskNumber;
  1488. }
  1489. }
  1490. else if (field is DFLayoutMultiSignaturePad)
  1491. {
  1492. var databutton = view as DataButtonControl;
  1493. if (!string.IsNullOrWhiteSpace(databutton.Data))
  1494. userInput = databutton.Data;
  1495. }
  1496. //add the field name and input to 'results' dictionary for processing outside of QAFormViewer
  1497. if (!String.IsNullOrWhiteSpace(userInput) && AddToDictionary)
  1498. {
  1499. if (field is DFLayoutLookupField)
  1500. { /*do nothing as results have already been added*/ }
  1501. else
  1502. {
  1503. try
  1504. {
  1505. results.Add(field.Name, userInput);
  1506. }
  1507. catch (Exception e)
  1508. {
  1509. errors.Add(e.Message);
  1510. }
  1511. if (RetainedResults.IsFormRetained)
  1512. {
  1513. AddRetainedToDictionary(field, userInput);
  1514. }
  1515. }
  1516. }
  1517. else CheckRequired(field);
  1518. return userInput;
  1519. }
  1520. private void AddPropertyToDictionary(DFLayoutField field, String userInput)
  1521. {
  1522. if (!string.IsNullOrWhiteSpace(userInput))
  1523. {
  1524. try
  1525. {
  1526. string property = "";
  1527. if (field is DFLayoutStringField)
  1528. property = (field as DFLayoutStringField).Properties.Property;
  1529. else if (field is DFLayoutIntegerField)
  1530. property = (field as DFLayoutIntegerField).Properties.Property;
  1531. else if (field is DFLayoutDoubleField)
  1532. property = (field as DFLayoutDoubleField).Properties.Property;
  1533. else if (field is DFLayoutBooleanField)
  1534. property = (field as DFLayoutBooleanField).Properties.Property;
  1535. else if (field is DFLayoutDateField)
  1536. property = (field as DFLayoutDateField).Properties.Property;
  1537. else if (field is DFLayoutTimeField)
  1538. property = (field as DFLayoutTimeField).Properties.Property;
  1539. else if (field is DFLayoutOptionField)
  1540. property = (field as DFLayoutOptionField).Properties.Property;
  1541. else if (field is DFLayoutLookupField)
  1542. property = (field as DFLayoutLookupField).Properties.Property;
  1543. //'propertyResults' dictionary for processing outside of QAFormViewer
  1544. if (!string.IsNullOrWhiteSpace(property)) propertyResults.Add(property, userInput);
  1545. }
  1546. catch (Exception e)
  1547. {
  1548. errors.Add(e.Message);
  1549. return;
  1550. }
  1551. }
  1552. }
  1553. private async void AddRetainedToDictionary(DFLayoutField field, string userInput)
  1554. {
  1555. await Task.Run(() =>
  1556. {
  1557. try
  1558. {
  1559. if (field is DFLayoutStringField)
  1560. {
  1561. if ((field as DFLayoutStringField).Properties.Retain)
  1562. RetainedResults.Results.Add(field.Name, userInput);
  1563. }
  1564. else if (field is DFLayoutIntegerField)
  1565. {
  1566. if ((field as DFLayoutIntegerField).Properties.Retain)
  1567. RetainedResults.Results.Add(field.Name, userInput);
  1568. }
  1569. else if (field is DFLayoutDoubleField)
  1570. {
  1571. if ((field as DFLayoutDoubleField).Properties.Retain)
  1572. RetainedResults.Results.Add(field.Name, userInput);
  1573. }
  1574. else if (field is DFLayoutBooleanField)
  1575. {
  1576. if ((field as DFLayoutBooleanField).Properties.Retain)
  1577. RetainedResults.Results.Add(field.Name, userInput);
  1578. }
  1579. else if (field is DFLayoutDateField)
  1580. {
  1581. if ((field as DFLayoutDateField).Properties.Retain)
  1582. RetainedResults.Results.Add(field.Name, userInput);
  1583. }
  1584. else if (field is DFLayoutTimeField)
  1585. {
  1586. if ((field as DFLayoutTimeField).Properties.Retain)
  1587. RetainedResults.Results.Add(field.Name, userInput);
  1588. }
  1589. else if (field is DFLayoutOptionField)
  1590. {
  1591. if ((field as DFLayoutOptionField).Properties.Retain)
  1592. RetainedResults.Results.Add(field.Name, userInput);
  1593. }
  1594. }
  1595. catch (Exception e)
  1596. {
  1597. errors.Add("Retained results error: " + e.Message);
  1598. }
  1599. });
  1600. }
  1601. #endregion
  1602. #region Checks / Custom methods
  1603. private void CheckRequired(DFLayoutField field)
  1604. {
  1605. if (field is DFLayoutStringField)
  1606. {
  1607. if ((field as DFLayoutStringField).Properties.Required)
  1608. {
  1609. isRequiredEmpty = true;
  1610. isRequiredMessage = (field as DFLayoutStringField).Description;
  1611. }
  1612. }
  1613. else if (field is DFLayoutIntegerField)
  1614. {
  1615. if ((field as DFLayoutIntegerField).Properties.Required)
  1616. {
  1617. isRequiredEmpty = true;
  1618. isRequiredMessage = (field as DFLayoutIntegerField).Description;
  1619. }
  1620. }
  1621. else if (field is DFLayoutDoubleField)
  1622. {
  1623. if ((field as DFLayoutDoubleField).Properties.Required)
  1624. {
  1625. {
  1626. isRequiredEmpty = true;
  1627. isRequiredMessage = (field as DFLayoutIntegerField).Description;
  1628. }
  1629. }
  1630. }
  1631. else if (field is DFLayoutBooleanField)
  1632. {
  1633. if ((field as DFLayoutBooleanField).Properties.Required)
  1634. {
  1635. {
  1636. isRequiredEmpty = true;
  1637. isRequiredMessage = (field as DFLayoutBooleanField).Description;
  1638. }
  1639. }
  1640. }
  1641. else if (field is DFLayoutDateField)
  1642. {
  1643. if ((field as DFLayoutDateField).Properties.Required)
  1644. {
  1645. {
  1646. isRequiredEmpty = true;
  1647. isRequiredMessage = (field as DFLayoutDateField).Description;
  1648. }
  1649. }
  1650. }
  1651. else if (field is DFLayoutTimeField)
  1652. {
  1653. if ((field as DFLayoutTimeField).Properties.Required)
  1654. {
  1655. {
  1656. isRequiredEmpty = true;
  1657. isRequiredMessage = (field as DFLayoutTimeField).Description;
  1658. }
  1659. }
  1660. }
  1661. else if (field is DFLayoutOptionField)
  1662. {
  1663. if ((field as DFLayoutOptionField).Properties.Required)
  1664. {
  1665. {
  1666. isRequiredEmpty = true;
  1667. isRequiredMessage = (field as DFLayoutOptionField).Description;
  1668. }
  1669. }
  1670. }
  1671. else if (field is DFLayoutLookupField)
  1672. {
  1673. if ((field as DFLayoutLookupField).Properties.Required)
  1674. {
  1675. {
  1676. isRequiredEmpty = true;
  1677. isRequiredMessage = (field as DFLayoutLookupField).Description;
  1678. }
  1679. }
  1680. }
  1681. else if (field is DFLayoutSignaturePad)
  1682. {
  1683. if ((field as DFLayoutSignaturePad).Properties.Required)
  1684. {
  1685. {
  1686. isRequiredEmpty = true;
  1687. isRequiredMessage = (field as DFLayoutSignaturePad).Description;
  1688. }
  1689. }
  1690. }
  1691. else if (field is DFLayoutEmbeddedImage)
  1692. {
  1693. if ((field as DFLayoutEmbeddedImage).Properties.Required)
  1694. {
  1695. {
  1696. isRequiredEmpty = true;
  1697. isRequiredMessage = (field as DFLayoutEmbeddedImage).Description;
  1698. }
  1699. }
  1700. }
  1701. else if (field is DFLayoutMultiImage)
  1702. {
  1703. if ((field as DFLayoutMultiImage).Properties.Required)
  1704. {
  1705. {
  1706. isRequiredEmpty = true;
  1707. isRequiredMessage = (field as DFLayoutMultiImage).Description;
  1708. }
  1709. }
  1710. }
  1711. else if (field is DFLayoutMultiSignaturePad)
  1712. {
  1713. if ((field as DFLayoutMultiSignaturePad).Properties.Required)
  1714. {
  1715. {
  1716. isRequiredEmpty = true;
  1717. isRequiredMessage = (field as DFLayoutMultiSignaturePad).Description;
  1718. }
  1719. }
  1720. }
  1721. }
  1722. private string ImagesToBase64(List<Image> images)
  1723. {
  1724. List<string> strings = new List<string>();
  1725. foreach (Image image in images)
  1726. {
  1727. strings.Add(ImageSourceToBase64(image.Source));
  1728. }
  1729. return Serialization.Serialize(strings);
  1730. }
  1731. private string ImageSourceToBase64(ImageSource source)
  1732. {
  1733. StreamImageSource streamImageSource = (StreamImageSource)source;
  1734. System.Threading.CancellationToken cancellationToken = System.Threading.CancellationToken.None;
  1735. Task<Stream> task = streamImageSource.Stream(cancellationToken);
  1736. Stream stream = task.Result;
  1737. byte[] bytes = new byte[stream.Length];
  1738. stream.Read(bytes, 0, bytes.Length);
  1739. string s = Convert.ToBase64String(bytes, Base64FormattingOptions.InsertLineBreaks);
  1740. return s;
  1741. }
  1742. private string BytesToBase64(byte[] bytes)
  1743. {
  1744. string s = Convert.ToBase64String(bytes, Base64FormattingOptions.InsertLineBreaks);
  1745. return s;
  1746. }
  1747. private string FindIDForDesignLookupField(DataButtonControl button)
  1748. {
  1749. try
  1750. {
  1751. string userInputValue = button.Data;
  1752. string guidString = "";
  1753. if (userInputValue != nullOrInvalidType)
  1754. {
  1755. foreach (KeyValuePair<DFLayoutLookupField, Dictionary<Guid, string>> pair in dfLayoutLookupFieldLookupOptions)
  1756. {
  1757. foreach (KeyValuePair<Guid, string> innerPair in pair.Value)
  1758. {
  1759. if (innerPair.Value == userInputValue)
  1760. {
  1761. guidString = innerPair.Key.ToString();
  1762. }
  1763. }
  1764. }
  1765. }
  1766. return guidString;
  1767. }
  1768. catch
  1769. {
  1770. return "";
  1771. }
  1772. }
  1773. #endregion
  1774. #region Save Completion
  1775. //point of determination for whether or not QA form gets completed or saved for later
  1776. private void UpdateInstanceAndModel(bool saveForLater)
  1777. {
  1778. if (results.Count != 0)
  1779. {
  1780. if (!saveForLater)
  1781. {
  1782. CompleteForm();
  1783. }
  1784. model.Instance.FormCompletedBy.ID = userID;
  1785. if (digitalFormID != Guid.Empty) model.Instance.Form.ID = digitalFormID;
  1786. DigitalForm.SerializeFormData(model.Instance, QueryVariables(model.Instance), results.ToDictionary(x => x.Key, x => x.Value as object));
  1787. FormData = model.Instance.FormData;
  1788. if (model.Instance.FormStarted == DateTime.MinValue)
  1789. {
  1790. model.Instance.FormStarted = timeStarted;
  1791. }
  1792. TimeSpan span = DateTime.Now - timeStarted;
  1793. model.Instance.FormOpen = model.Instance.FormOpen + span;
  1794. model.Update(null);
  1795. }
  1796. }
  1797. public List<DigitalFormVariable> QueryVariables(IDigitalFormInstance form)
  1798. {
  1799. List<DigitalFormVariable> variables = new List<DigitalFormVariable>();
  1800. var table = new Client<DigitalFormVariable>().Query(
  1801. new Filter<DigitalFormVariable>(x => x.Form.ID).IsEqualTo(form.Form.ID),
  1802. new Columns<DigitalFormVariable>(x => x.Code, x => x.Parameters, x => x.Description, x => x.VariableType),
  1803. null
  1804. );
  1805. foreach (CoreRow coreRow in table.Rows)
  1806. {
  1807. var variable = coreRow.ToObject<DigitalFormVariable>();
  1808. variables.Add(variable);
  1809. }
  1810. return variables;
  1811. }
  1812. private void CompleteForm()
  1813. {
  1814. model.Instance.FormCompleted = DateTime.Now;
  1815. FormCompleted = model.Instance.FormCompleted;
  1816. model.Instance.Location.Longitude = location.Longitude;
  1817. model.Instance.Location.Latitude = location.Latitude;
  1818. model.Instance.Location.Timestamp = model.Instance.FormCompleted;
  1819. }
  1820. #endregion
  1821. #endregion
  1822. #region Expressions
  1823. public object GetFieldValue(string field)
  1824. {
  1825. try
  1826. {
  1827. Tuple<DFLayoutField, View> tuple = FindView(field);
  1828. return GetValueFromView(tuple.Item1, tuple.Item2);
  1829. }
  1830. catch
  1831. {
  1832. return "";
  1833. }
  1834. }
  1835. public void SetFieldValue(string field, object value)
  1836. {
  1837. try
  1838. {
  1839. Tuple<DFLayoutField, View> tuple = FindView(field);
  1840. SetValueOfView(tuple.Item1, tuple.Item2, value);
  1841. }
  1842. catch { }
  1843. }
  1844. private void SetValueOfView(DFLayoutField field, View view, object value)
  1845. {
  1846. if (field is DFLayoutBooleanField)
  1847. (view as CustomBoolean).Value = (bool)value;
  1848. else if (field is DFLayoutStringField || field is DFLayoutIntegerField || field is DFLayoutDoubleField)
  1849. {
  1850. if (field is DFLayoutStringField && (field as DFLayoutStringField).Properties.PopupEditor)
  1851. {
  1852. (view as DataButtonControl).Data = value.ToString();
  1853. (view as DataButtonControl).Text = value.ToString();
  1854. }
  1855. else
  1856. (view as Editor).Text = value.ToString();
  1857. }
  1858. else if (field is DFLayoutDateField)
  1859. (view as DatePicker).Date = (DateTime)(value as DateTime?);
  1860. else if (field is DFLayoutDateTimeField)
  1861. (view as TimePicker).Time = (TimeSpan)(value as TimeSpan?);
  1862. else if (field is DFLayoutOptionField)
  1863. AssignPickerOption(view, field as DFLayoutOptionField, value as string);
  1864. else if (field is DFLayoutLookupField)
  1865. AssignLookupOption(view, value as string);
  1866. else if (field is DFLayoutEmbeddedImage)
  1867. AssignImage(view, value as byte[]);
  1868. }
  1869. private void AssignImage(View view, byte[] bytes)
  1870. {
  1871. var imageCapture = view as EmbeddedImageCapture;
  1872. imageCapture.DataToImage(bytes);
  1873. }
  1874. private void AssignLookupOption(View view, string value)
  1875. {
  1876. if (view is DataButtonControl)
  1877. {
  1878. (view as DataButtonControl).Text = value;
  1879. (view as DataButtonControl).Data = value;
  1880. }
  1881. else if (view is FrameButton) //currently only used for Products - we already have the Product.ID in Framebutton.Data (saved as Code,ID)
  1882. {
  1883. (view as FrameButton).SetButtonText(value);
  1884. (view as FrameButton).Data = value + "," + Guid.Empty.ToString();
  1885. }
  1886. }
  1887. private Tuple<DFLayoutField, View> FindView(string field)
  1888. {
  1889. DFLayoutField dflayoutfield = pairs.Keys.FirstOrDefault(x => x.Name == field);
  1890. View view = pairs[dflayoutfield];
  1891. return new Tuple<DFLayoutField, View>(dflayoutfield, view);
  1892. }
  1893. private void AssignPickerOption(View view, DFLayoutOptionField field, string value)
  1894. {
  1895. string s = field.Properties.Options;
  1896. string[] substrings = s.Split(',');
  1897. var optionList = substrings.ToList();
  1898. if (Device.RuntimePlatform == Device.iOS)
  1899. {
  1900. var iOSPicker = view as CustomPickeriOS;
  1901. iOSPicker.SelectedIndex = optionList.IndexOf(value);
  1902. }
  1903. else
  1904. {
  1905. var picker = view as Picker;
  1906. picker.SelectedIndex = optionList.IndexOf(value);
  1907. }
  1908. }
  1909. private object GetValueFromView(DFLayoutField field, View view)
  1910. {
  1911. if (field is DFLayoutBooleanField)
  1912. return (view as CustomBoolean).Value;
  1913. if (field is DFLayoutStringField)
  1914. {
  1915. if ((field as DFLayoutStringField).Properties.PopupEditor)
  1916. return (view as DataButtonControl).Data;
  1917. else
  1918. return (view as Editor).Text;
  1919. }
  1920. else if (field is DFLayoutIntegerField)
  1921. return int.Parse((view as Editor).Text);
  1922. else if (field is DFLayoutDoubleField)
  1923. return double.Parse((view as Editor).Text);
  1924. else if (field is DFLayoutDateField)
  1925. return (view as DatePicker).Date;
  1926. else if (field is DFLayoutDateTimeField)
  1927. return (view as TimePicker).Time;
  1928. else if (field is DFLayoutOptionField)
  1929. return GetStringFromOptionField(view);
  1930. else if (field is DFLayoutLookupField)
  1931. return GetStringFromLookupField(view);
  1932. else if (field is DFLayoutSignaturePad)
  1933. return GetByteArrayFromSignaturePad(view, field.Name);
  1934. else if (field is DFLayoutEmbeddedImage)
  1935. return GetByteArrayFromEmbeddedImage(view);
  1936. else if (field is DFLayoutMultiImage)
  1937. return GetByteArrayListFromMultiImage(view);
  1938. else return "";
  1939. }
  1940. private object GetByteArrayListFromMultiImage(View view)
  1941. {
  1942. List<byte[]> list = new List<byte[]>();
  1943. var multiImage = view as MultiImageCapture;
  1944. if (multiImage.Images.Count > 0)
  1945. {
  1946. foreach (Image image in multiImage.Images)
  1947. {
  1948. string base64 = ImageSourceToBase64(image.Source);
  1949. list.Add(Convert.FromBase64String(base64));
  1950. }
  1951. }
  1952. return list;
  1953. }
  1954. private object GetByteArrayFromEmbeddedImage(View view)
  1955. {
  1956. var embeddedImage = view as EmbeddedImageCapture;
  1957. if (embeddedImage.Image.Source != null)
  1958. {
  1959. string base64 = ImageSourceToBase64(embeddedImage.Image.Source);
  1960. return Convert.FromBase64String(base64);
  1961. }
  1962. else
  1963. return null;
  1964. }
  1965. private byte[] GetByteArrayFromSignaturePad(View view, string name)
  1966. {
  1967. var grid = view as Grid;
  1968. var signaturePad = grid.Children.OfType<SfSignaturePad>().FirstOrDefault();
  1969. if (useSavedSignatures.Contains(name))
  1970. {
  1971. return Application.Current.Properties["SavedSignature"] as byte[];
  1972. }
  1973. else
  1974. {
  1975. signaturePad.Save();
  1976. if (signaturePad.ImageSource != null)
  1977. {
  1978. string base64 = ImageSourceToBase64(signaturePad.ImageSource);
  1979. return Convert.FromBase64String(base64);
  1980. }
  1981. else
  1982. return null;
  1983. }
  1984. }
  1985. private object GetStringFromLookupField(View view)
  1986. {
  1987. string value = "";
  1988. if (view is DataButtonControl)
  1989. {
  1990. var button = view as DataButtonControl;
  1991. value = FindIDForDesignLookupField(button); //userinput is used to set guid later on for properties, but will not get added to form data only for lookupfields
  1992. }
  1993. else if (view is FrameButton) //currently only used for Products - we already have the Product.ID in Framebutton.Data (saved as Code,ID)
  1994. {
  1995. FrameButton framebutton = view as FrameButton;
  1996. if (!string.IsNullOrWhiteSpace(framebutton.Data))
  1997. {
  1998. string[] buttonData = framebutton.Data.Split(',');
  1999. value = buttonData[1]; //[1] is product id as string
  2000. }
  2001. }
  2002. return value;
  2003. }
  2004. private string GetStringFromOptionField(View view)
  2005. {
  2006. if (Device.RuntimePlatform == Device.iOS)
  2007. {
  2008. var iOSPicker = view as CustomPickeriOS;
  2009. if (iOSPicker.SelectedIndex != -1)
  2010. {
  2011. return iOSPicker.SelectedItem.ToString();
  2012. }
  2013. else
  2014. return "";
  2015. }
  2016. else
  2017. {
  2018. var picker = view as Picker;
  2019. if (picker.SelectedIndex != -1)
  2020. {
  2021. return picker.SelectedItem.ToString();
  2022. }
  2023. else
  2024. return "";
  2025. }
  2026. }
  2027. public object GetFieldData(string fieldName, string dataField)
  2028. {
  2029. Tuple<DFLayoutField, View> tuple = FindView(fieldName);
  2030. try
  2031. {
  2032. if (tuple.Item1 is DFLayoutLookupField)
  2033. {
  2034. DFLayoutLookupField field = tuple.Item1 as DFLayoutLookupField;
  2035. string type = field.Properties.LookupType;
  2036. Type lookuptype = CoreUtils.GetEntityOrNull(type);
  2037. if (lookuptype == typeof(Product))
  2038. {
  2039. var framebutton = tuple.Item2 as FrameButton;
  2040. string[] buttonData = framebutton.Data.Split(',');
  2041. string id = buttonData[1]; //[1] is product id as string
  2042. CoreTable table = new Client<Product>().Query(new Filter<Product>(x => x.ID).IsEqualTo(Guid.Parse(id)), new Columns<Product>(x => x.Image.ID));
  2043. if (table.Rows.Any())
  2044. {
  2045. Guid returnid = table.Rows.FirstOrDefault().Get<Product, Guid>(x => x.Image.ID);
  2046. return returnid;
  2047. }
  2048. else
  2049. return null;
  2050. }
  2051. else
  2052. {
  2053. var button = tuple.Item2 as DataButtonControl;
  2054. Dictionary<string, object> dict = button.ExtraData[button.ChosenID];
  2055. return dict[dataField];
  2056. }
  2057. }
  2058. else
  2059. return null;
  2060. }
  2061. catch
  2062. {
  2063. return null;
  2064. }
  2065. }
  2066. public void SetFieldColour(string field, System.Drawing.Color? colour = null)
  2067. {
  2068. if (colour != null)
  2069. {
  2070. try
  2071. {
  2072. System.Drawing.Color color = (System.Drawing.Color)colour;
  2073. FindView(field).Item2.BackgroundColor = Color.FromRgba(
  2074. Convert.ToDouble(color.R),
  2075. Convert.ToDouble(color.G),
  2076. Convert.ToDouble(color.B),
  2077. Convert.ToDouble(color.A));
  2078. }
  2079. catch { }
  2080. }
  2081. }
  2082. #endregion
  2083. }
  2084. }