QAFormViewer.cs 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Threading.Tasks;
  4. using System.Linq;
  5. using Xamarin.Forms;
  6. using InABox.Core;
  7. using InABox.Mobile;
  8. using PRSClasses;
  9. namespace PRS.Mobile
  10. {
  11. public class QAFormViewer : Grid, IDFRenderer
  12. {
  13. #region Fields
  14. // This connects the DFLayout elements to the respective UI elements
  15. public readonly Dictionary<DFLayoutField, IDigitalFormField> Bindings = new();
  16. // These get saved into FormData
  17. public DFLoadStorage Storage { get; private set; }
  18. // These are used to pre-populate the next instance of this form
  19. public DFLoadStorage RetainedData { get; private set; }
  20. //public readonly Dictionary<DFLayoutLookupField, Dictionary<Guid, string>> dfLayoutLookupFieldLookupOptions = new();
  21. private DFLayout _layout = new();
  22. private IDigitalFormDataModel? _model;
  23. const string nullOrInvalidType = "Null or Invalid Type";
  24. private readonly List<string> useSavedSignatures = new();
  25. public readonly List<string> errors = new();
  26. public bool isRequiredEmpty { get; set; }
  27. public string isRequiredMessage { get; set; } = "";
  28. private readonly Location location = new();
  29. private readonly Color isRequiredColor = Color.DarkOrange;
  30. private readonly Color isRequiredFrame = Color.Firebrick;
  31. private DateTime timeStarted = DateTime.MinValue;
  32. readonly List<DigitalFormHeader> headersToCollapse = new();
  33. #endregion
  34. #region Constructor
  35. public QAFormViewer()
  36. {
  37. Storage = new DFLoadStorage();
  38. RetainedData = new DFLoadStorage();
  39. }
  40. public QAFormViewer(IDigitalFormDataModel model, DFLayout layout,
  41. Guid job = default) : this()
  42. {
  43. Load(model, layout, job);
  44. }
  45. public void Load(IDigitalFormDataModel model, DFLayout layout, Guid job = default)
  46. {
  47. GetLocation();
  48. timeStarted = DateTime.Now;
  49. _model = model;
  50. _layout = layout;
  51. _layout.Renderer = this;
  52. isRequiredEmpty = false;
  53. isRequiredMessage = "";
  54. LoadFormLayout();
  55. Storage = DigitalForm.DeserializeFormData(_model.Instance) ?? new DFLoadStorage();
  56. LoadData();
  57. }
  58. #endregion
  59. #region Location
  60. private async void GetLocation()
  61. {
  62. await Task.Run(() =>
  63. {
  64. LocationServices locationServices = new LocationServices();
  65. locationServices.OnLocationFound += LocationFound;
  66. locationServices.OnLocationError += LocationError;
  67. locationServices.GetLocation();
  68. });
  69. }
  70. private void LocationFound(LocationServices sender)
  71. {
  72. location.Latitude = sender.Latitude;
  73. location.Longitude = sender.Longitude;
  74. }
  75. private void LocationError(LocationServices sender, Exception error)
  76. {
  77. errors.Add("Location error: " + error.Message);
  78. }
  79. #endregion Location
  80. #region Load and Save Data
  81. public void DuplicateInstance()
  82. {
  83. _model.DuplicateInstance();
  84. }
  85. public void LoadData()
  86. {
  87. foreach (DFLayoutField field in Bindings.Keys)
  88. {
  89. try
  90. {
  91. if (RetainedData.HasValue(field.Name))
  92. Bindings[field].Deserialize(RetainedData.GetEntry(field.Name));
  93. else if (Storage.HasValue(field.Name))
  94. Bindings[field].Deserialize(Storage.GetEntry(field.Name));
  95. else
  96. Bindings[field].Value = CoreUtils.GetPropertyValue(field.GetProperties(), "Default");
  97. _layout.ChangeField(field.Name);
  98. }
  99. catch (Exception ex)
  100. {
  101. InABox.Mobile.MobileLogging.Log(ex,$"LoadData({field.Name})");
  102. }
  103. }
  104. }
  105. public void SaveData(bool saveForLater, bool deleteform)
  106. {
  107. try
  108. {
  109. var save = new DFSaveStorage();
  110. var retained = new DFSaveStorage();
  111. foreach (DFLayoutField field in Bindings.Keys)
  112. {
  113. var entry = save.GetEntry(field.Name);
  114. Bindings[field].Serialize(entry);
  115. if (field.GetProperties().Retain)
  116. {
  117. var retentry = retained.GetEntry(field.Name);
  118. Bindings[field].Serialize(retentry);
  119. }
  120. }
  121. UpdateModel(save, saveForLater, deleteform);
  122. Storage.Clear();
  123. RetainedData.Load(retained.FormData, retained.BlobData);
  124. }
  125. catch (Exception ex)
  126. {
  127. InABox.Mobile.MobileLogging.Log(ex,"SaveData");
  128. }
  129. }
  130. #endregion
  131. #region Load Form Layout
  132. private void LoadFormLayout()
  133. {
  134. RowDefinitions.Clear();
  135. foreach (var row in _layout.RowHeights)
  136. {
  137. RowDefinition def = new RowDefinition { Height = new GridLength(1, GridUnitType.Auto) };
  138. SetRowHeight(row, def);
  139. RowDefinitions.Add(def);
  140. }
  141. ColumnDefinitions.Clear();
  142. foreach (var col in _layout.ColumnWidths)
  143. {
  144. ColumnDefinition def = new ColumnDefinition { Width = new GridLength(1, GridUnitType.Auto) };
  145. def = SetColumnWidth(col, def);
  146. ColumnDefinitions.Add(def);
  147. }
  148. Children.Clear();
  149. foreach (DFLayoutControl element in _layout.Elements)
  150. LoadViewAccordingToElement(element);
  151. foreach (var header in headersToCollapse)
  152. AdjustHeaderSection(header, false);
  153. }
  154. private static void SetRowHeight(string row, RowDefinition def)
  155. {
  156. if (int.TryParse(row, out int rowHeight))
  157. def.Height = new GridLength(Math.Max(60, rowHeight), GridUnitType.Absolute);
  158. else if (row.Contains("*"))
  159. {
  160. def.Height = int.TryParse(row.Substring(0, row.IndexOf("*")), out int result)
  161. ? new GridLength(result, GridUnitType.Star)
  162. : new GridLength(1, GridUnitType.Star);
  163. }
  164. else
  165. def.Height = new GridLength(1, GridUnitType.Auto);
  166. }
  167. private static ColumnDefinition SetColumnWidth(string col, ColumnDefinition def)
  168. {
  169. if (int.TryParse(col, out int colWidth))
  170. def = new ColumnDefinition { Width = new GridLength(colWidth, GridUnitType.Absolute) };
  171. else if (col.Contains("*"))
  172. {
  173. def = int.TryParse(col.Substring(0, col.IndexOf("*")), out int result)
  174. ? new ColumnDefinition { Width = new GridLength(result, GridUnitType.Star) }
  175. : new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) };
  176. }
  177. return def;
  178. }
  179. private void LoadViewAccordingToElement(DFLayoutControl element)
  180. {
  181. // Not sure why this is here - perhaps to ry and handle malformed element definitions?
  182. if (string.IsNullOrEmpty(element.Description))
  183. return;
  184. if (element is DFLayoutLabel l)
  185. {
  186. var result = new DigitalFormLabel() { Definition = l };
  187. AddViewToGrid(result, element);
  188. }
  189. else if (element is DFLayoutImage img )
  190. {
  191. var result = new DigitalFormImage() { Definition = img };
  192. AddViewToGrid(result, element);
  193. }
  194. else if (element is DFLayoutHeader hdr)
  195. {
  196. var result = new DigitalFormHeader() { Definition = hdr };
  197. result.CollapsedChanged += (sender, args) => AdjustHeaderSection(result, result.Collapsed);
  198. if (hdr.Collapsed)
  199. headersToCollapse.Add(result);
  200. AddViewToGrid(result, element);
  201. }
  202. else if (element is DFLayoutBooleanField b)
  203. CreateView<DigitalFormBoolean, DFLayoutBooleanField, DFLayoutBooleanFieldProperties, bool, bool?>(b);
  204. else if (element is DFLayoutStringField s)
  205. {
  206. if (s.Properties.PopupEditor)
  207. CreateView<DigitalFormStringPopup, DFLayoutStringField, DFLayoutStringFieldProperties, string, string?>(s);
  208. else if (s.Properties.TextWrapping)
  209. CreateView<DigitalFormStringEditor, DFLayoutStringField, DFLayoutStringFieldProperties, string, string?>(s);
  210. else
  211. CreateView<DigitalFormStringEntry, DFLayoutStringField, DFLayoutStringFieldProperties, string, string?>(s);
  212. }
  213. else if (element is DFLayoutIntegerField i)
  214. CreateView<DigitalFormIntegerEntry, DFLayoutIntegerField, DFLayoutIntegerFieldProperties, int, int?>(i);
  215. else if (element is DFLayoutDoubleField d)
  216. CreateView<DigitalFormDoubleEntry, DFLayoutDoubleField, DFLayoutDoubleFieldProperties, double, double?>(d);
  217. else if (element is DFLayoutDateField df)
  218. CreateView<DigitalFormDateEntry, DFLayoutDateField, DFLayoutDateFieldProperties, DateTime, DateTime?>(df);
  219. else if (element is DFLayoutTimeField tf)
  220. CreateView<DigitalFormTimeEntry, DFLayoutTimeField, DFLayoutTimeFieldProperties, TimeSpan,TimeSpan?>(tf);
  221. else if (element is DFLayoutOptionField of)
  222. {
  223. if (of.Properties.OptionType == DFLayoutOptionType.Radio)
  224. CreateView<DigitalFormOptionRadioList, DFLayoutOptionField, DFLayoutOptionFieldProperties, string, string?>(of);
  225. else if (of.Properties.OptionType == DFLayoutOptionType.Buttons)
  226. CreateView<DigitalFormOptionButtonList, DFLayoutOptionField, DFLayoutOptionFieldProperties, string, string?>(of);
  227. else
  228. CreateView<DigitalFormOptionComboBox, DFLayoutOptionField, DFLayoutOptionFieldProperties, string, string?>(of);
  229. }
  230. else if (element is DFLayoutLookupField lf)
  231. {
  232. if (lf.Properties.DisplayType == DFLayoutLookupDisplayType.Combo)
  233. CreateView<DigitalFormLookupComboBox, DFLayoutLookupField, DFLayoutLookupFieldProperties, Guid, DFLayoutLookupValue>(lf);
  234. else
  235. CreateView<DigitalFormLookupButton, DFLayoutLookupField, DFLayoutLookupFieldProperties, Guid, DFLayoutLookupValue>(lf);
  236. }
  237. else if (element is DFLayoutSignaturePad sp)
  238. CreateView<DigitalFormSignature, DFLayoutSignaturePad, DFLayoutSignaturePadProperties, byte[], byte[]?>(sp);
  239. else if (element is DFLayoutEmbeddedImage ei)
  240. CreateView<DigitalFormEmbeddedImage, DFLayoutEmbeddedImage, DFLayoutEmbeddedImageProperties, Guid, DFLayoutEmbeddedMediaValue>(ei);
  241. else if (element is DFLayoutVideoField ev)
  242. CreateView<DigitalFormEmbeddedVideo, DFLayoutVideoField, DFLayoutVideoFieldProperties, byte[], DFLayoutEmbeddedMediaValue>(ev);
  243. else if (element is DFLayoutMultiImage mi)
  244. CreateView<DigitalFormMultiImage, DFLayoutMultiImage, DFLayoutMultiImageProperties, List<Guid>, DFLayoutEmbeddedMediaValues>(mi);
  245. else if (element is DFLayoutMultiSignaturePad ms)
  246. {
  247. CreateView<DigitalFormMultiSignature, DFLayoutMultiSignaturePad, DFLayoutMultiSignaturePadProperties,
  248. Dictionary<string, byte[]>, Dictionary<string, byte[]>?>(ms);
  249. //var tuple = LoadMultiSignaturePad(element);
  250. //AddViewToGrid(tuple.Item1, element);
  251. }
  252. else if (element is DFLayoutAddTaskField at)
  253. {
  254. CreateView<DigitalFormAddTask, DFLayoutAddTaskField, DFLayoutAddTaskFieldProperties,
  255. string?, string?>(at);
  256. //var tuple = LoadAddTaskField(element);
  257. //AddViewToGrid(tuple.Item1, element);
  258. }
  259. }
  260. private TField CreateView<TField, TDefinition, TProperties, TValue, TSerialized>(TDefinition definition)
  261. where TField : View, IDigitalFormField<TDefinition, TProperties, TValue, TSerialized>, new()
  262. where TDefinition : DFLayoutField<TProperties>
  263. where TProperties : DFLayoutFieldProperties<TValue, TSerialized>, new()
  264. {
  265. TField item = new TField()
  266. {
  267. Definition = definition,
  268. IsEnabled = !definition.GetProperties().Secure
  269. && _model.Instance.FormCompleted.IsEmpty()
  270. && string.IsNullOrWhiteSpace(definition.GetPropertyValue<string>("Expression")),
  271. };
  272. item.ValueChanged += (sender, args) =>
  273. {
  274. // Update Object?
  275. var property = args.Definition.GetProperties().Property;
  276. if (!String.IsNullOrWhiteSpace(property))
  277. CoreUtils.SetPropertyValue(_model.Entity,property,args.Value);
  278. foreach (var other in Bindings.Keys.Where(x=>x.Name != args.Definition.Name))
  279. {
  280. var linked = other.GetProperties().Property;
  281. if (!String.IsNullOrWhiteSpace(linked))
  282. {
  283. try
  284. {
  285. var linkedvalue = CoreUtils.GetPropertyValue(_model.Entity, linked);
  286. // Problem - linkedvalue might not be the same as the
  287. //CoreUtils.SetPropertyValue(pairs[other],"Value",linkedvalue);
  288. }
  289. catch (Exception e)
  290. {
  291. MobileLogging.Log(e,"QAFormViewer:Item.ValueChanged()");
  292. }
  293. }
  294. }
  295. // Update ChangedLinkedProperties?
  296. // Run Expressions and Scripts?
  297. // Update Dictionary?
  298. };
  299. Bindings[definition] = item;
  300. AddViewToGrid(item, definition);
  301. return item;
  302. }
  303. private void AddViewToGrid(View view, DFLayoutControl element)
  304. {
  305. //rows and columns coming in from the desktop designer start from 1, not 0 (most of the time??)
  306. SetRow(view, Math.Max(0,element.Row - 1));
  307. SetRowSpan(view, Math.Max(1,element.RowSpan));
  308. SetColumn(view, Math.Max(0,element.Column - 1));
  309. SetColumnSpan(view, Math.Max(1,element.ColumnSpan));
  310. Children.Add(view);
  311. }
  312. private void AdjustHeaderSection(DigitalFormHeader header, bool collapsed)
  313. {
  314. try
  315. {
  316. var thisHeaderRow = GetRow(header);
  317. var headerRows = Children.OfType<DigitalFormHeader>().Select(x => GetRow(x)).OrderBy(x=>x).ToArray();
  318. if (headerRows.Any())
  319. AdjustHeightsToNextHeader(headerRows, thisHeaderRow, collapsed);
  320. else
  321. AdjustHeightsBelowHeader(headerRows, thisHeaderRow, collapsed);
  322. }
  323. catch (Exception ex)
  324. {
  325. MobileLogging.Log(ex, "AdjustHeaderSection()");
  326. }
  327. }
  328. private void AdjustHeightsToNextHeader(int[] headerRows, int thisHeaderRow, bool collapsed)
  329. {
  330. int nextHeaderRow = headerRows[0];
  331. for (int i = thisHeaderRow + 1; i < nextHeaderRow; i++)
  332. AdjustHeight(i, collapsed);
  333. }
  334. private void AdjustHeightsBelowHeader(int[] headerRows, int thisHeaderRow, bool collapsed)
  335. {
  336. for (int i = thisHeaderRow + 1; i < RowDefinitions.Count; i++)
  337. AdjustHeight(i, collapsed);
  338. }
  339. private void AdjustHeight(int i, bool collapsed)
  340. {
  341. var rowdef = RowDefinitions[i];
  342. if (collapsed)
  343. SetRowHeight(_layout.RowHeights[i], rowdef);
  344. else
  345. rowdef.Height = 0;
  346. }
  347. // private Tuple<View, bool> LoadMultiSignaturePad(DFLayoutControl element)
  348. // {
  349. // string value = "";
  350. // DFLayoutMultiSignaturePad dfLayoutMultiSignaturePad = element as DFLayoutMultiSignaturePad;
  351. // DataButtonControl button = new DataButtonControl
  352. // {
  353. // Text = "Add Signatures",
  354. // };
  355. // if (Storage.TryGetValue(dfLayoutMultiSignaturePad.Name, out value))
  356. // {
  357. // button.Data = value;
  358. // }
  359. // MultiSignaturePad multiSignaturePad = new MultiSignaturePad(button.Data);
  360. // multiSignaturePad.OnMultiSignatureSaved += (result) =>
  361. // {
  362. // button.Data = result;
  363. // };
  364. // button.Clicked += (object sender, MobileButtonClickEventArgs e) =>
  365. // {
  366. // Navigation.PushAsync(multiSignaturePad);
  367. // };
  368. //
  369. // if (dfLayoutMultiSignaturePad.Properties.Required)
  370. // {
  371. // button.BackgroundColor = isRequiredColor;
  372. // button.BorderColor = isRequiredFrame;
  373. // }
  374. // else if (!_model.Instance.FormCompleted.IsEmpty())
  375. // {
  376. // button.BackgroundColor = Color.Silver;
  377. // button.BorderColor = Color.Gray;
  378. // }
  379. //
  380. // return new Tuple<View, bool>(button, dfLayoutMultiSignaturePad.Properties.Required);
  381. // }
  382. // private Tuple<View, bool> LoadAddTaskField(DFLayoutControl element)
  383. // {
  384. // string value = "";
  385. // DFLayoutAddTaskField field = element as DFLayoutAddTaskField;
  386. // DFCreateTaskView taskView = new DFCreateTaskView();
  387. // taskView.OnAddTaskButtonClicked += () =>
  388. // {
  389. // AddEditTask addEditTask = new AddEditTask(Guid.Empty, "New task from Digital Form");
  390. // if (field.Properties.TaskType != null)
  391. // {
  392. // addEditTask.kanban.Type.ID = field.Properties.TaskType.ID;
  393. // try
  394. // {
  395. // addEditTask.kanban.Type.Description = new Client<KanbanType>().Query(
  396. // new Filter<KanbanType>(x => x.ID).IsEqualTo(field.Properties.TaskType.ID),
  397. // new Columns<KanbanType>(x => x.Description)
  398. // ).Rows.FirstOrDefault()?.Get<KanbanType,String>(c=>c.Description) ?? string.Empty;
  399. // }
  400. // catch (Exception ex)
  401. // {
  402. // MobileLogging.Log(ex,"LoadAddTaskField");
  403. // }
  404. // addEditTask.UpdateScreen(true);
  405. // }
  406. // addEditTask.OnTaskSaved += (taskNumber) =>
  407. // {
  408. // taskView.DisableButton();
  409. // taskView.TaskNumber = taskNumber.ToString();
  410. // };
  411. // Navigation.PushAsync(addEditTask);
  412. // };
  413. // if (Storage.TryGetValue(field.Name, out value))
  414. // {
  415. // taskView.TaskNumber = value;
  416. // taskView.DisableButton();
  417. // }
  418. //
  419. // return new Tuple<View, bool>(taskView, field.Properties.Required);
  420. // }
  421. #endregion
  422. #region Checks / Custom methods
  423. private void CheckRequired(DFLayoutField field)
  424. {
  425. if (field is DFLayoutStringField)
  426. {
  427. if ((field as DFLayoutStringField).Properties.Required)
  428. {
  429. isRequiredEmpty = true;
  430. isRequiredMessage = (field as DFLayoutStringField).Description;
  431. }
  432. }
  433. else if (field is DFLayoutIntegerField)
  434. {
  435. if ((field as DFLayoutIntegerField).Properties.Required)
  436. {
  437. isRequiredEmpty = true;
  438. isRequiredMessage = (field as DFLayoutIntegerField).Description;
  439. }
  440. }
  441. else if (field is DFLayoutDoubleField)
  442. {
  443. if ((field as DFLayoutDoubleField).Properties.Required)
  444. {
  445. {
  446. isRequiredEmpty = true;
  447. isRequiredMessage = (field as DFLayoutIntegerField).Description;
  448. }
  449. }
  450. }
  451. else if (field is DFLayoutBooleanField)
  452. {
  453. if ((field as DFLayoutBooleanField).Properties.Required)
  454. {
  455. {
  456. isRequiredEmpty = true;
  457. isRequiredMessage = (field as DFLayoutBooleanField).Description;
  458. }
  459. }
  460. }
  461. else if (field is DFLayoutDateField)
  462. {
  463. if ((field as DFLayoutDateField).Properties.Required)
  464. {
  465. {
  466. isRequiredEmpty = true;
  467. isRequiredMessage = (field as DFLayoutDateField).Description;
  468. }
  469. }
  470. }
  471. else if (field is DFLayoutTimeField)
  472. {
  473. if ((field as DFLayoutTimeField).Properties.Required)
  474. {
  475. {
  476. isRequiredEmpty = true;
  477. isRequiredMessage = (field as DFLayoutTimeField).Description;
  478. }
  479. }
  480. }
  481. else if (field is DFLayoutOptionField)
  482. {
  483. if ((field as DFLayoutOptionField).Properties.Required)
  484. {
  485. {
  486. isRequiredEmpty = true;
  487. isRequiredMessage = (field as DFLayoutOptionField).Description;
  488. }
  489. }
  490. }
  491. else if (field is DFLayoutLookupField)
  492. {
  493. if ((field as DFLayoutLookupField).Properties.Required)
  494. {
  495. {
  496. isRequiredEmpty = true;
  497. isRequiredMessage = (field as DFLayoutLookupField).Description;
  498. }
  499. }
  500. }
  501. else if (field is DFLayoutSignaturePad)
  502. {
  503. if ((field as DFLayoutSignaturePad).Properties.Required)
  504. {
  505. {
  506. isRequiredEmpty = true;
  507. isRequiredMessage = (field as DFLayoutSignaturePad).Description;
  508. }
  509. }
  510. }
  511. else if (field is DFLayoutEmbeddedImage)
  512. {
  513. if ((field as DFLayoutEmbeddedImage).Properties.Required)
  514. {
  515. {
  516. isRequiredEmpty = true;
  517. isRequiredMessage = (field as DFLayoutEmbeddedImage).Description;
  518. }
  519. }
  520. }
  521. else if (field is DFLayoutMultiImage)
  522. {
  523. if ((field as DFLayoutMultiImage).Properties.Required)
  524. {
  525. {
  526. isRequiredEmpty = true;
  527. isRequiredMessage = (field as DFLayoutMultiImage).Description;
  528. }
  529. }
  530. }
  531. else if (field is DFLayoutMultiSignaturePad)
  532. {
  533. if ((field as DFLayoutMultiSignaturePad).Properties.Required)
  534. {
  535. {
  536. isRequiredEmpty = true;
  537. isRequiredMessage = (field as DFLayoutMultiSignaturePad).Description;
  538. }
  539. }
  540. }
  541. }
  542. //
  543. // {
  544. // StreamImageSource streamImageSource = (StreamImageSource)source;
  545. // System.Threading.CancellationToken cancellationToken = System.Threading.CancellationToken.None;
  546. // Task<Stream> task = streamImageSource.Stream(cancellationToken);
  547. // Stream stream = task.Result;
  548. // byte[] bytes = new byte[stream.Length];
  549. // stream.Read(bytes, 0, bytes.Length);
  550. // string s = Convert.ToBase64String(bytes, Base64FormattingOptions.InsertLineBreaks);
  551. // return s;
  552. // }
  553. //
  554. // private string FindIDForDesignLookupField(DataButtonControl button)
  555. // {
  556. // try
  557. // {
  558. // string userInputValue = button.Data;
  559. // string guidString = "";
  560. // if (userInputValue != nullOrInvalidType)
  561. // {
  562. // foreach (KeyValuePair<DFLayoutLookupField, Dictionary<Guid, string>> pair in dfLayoutLookupFieldLookupOptions)
  563. // {
  564. // foreach (KeyValuePair<Guid, string> innerPair in pair.Value)
  565. // {
  566. // if (innerPair.Value == userInputValue)
  567. // {
  568. // guidString = innerPair.Key.ToString();
  569. // }
  570. // }
  571. // }
  572. // }
  573. //
  574. // return guidString;
  575. // }
  576. // catch (Exception e)
  577. // {
  578. // MobileLogging.Log(e,"FindIDForDesignLookupField");
  579. // return "";
  580. // }
  581. // }
  582. #endregion
  583. #region Save Completion
  584. //point of determination for whether or not QA form gets completed or saved for later
  585. private void UpdateModel(DFSaveStorage save, bool saveForLater, bool deleteform)
  586. {
  587. if (save.Count() > 0 && _model != null)
  588. {
  589. // Blobs are uploaded in the background by DigitalFormDocumentHandler class,
  590. // so the blob breakup doesn't have to happen anymore :-)
  591. DigitalForm.SerializeFormData(_model.Instance, _model.Variables, save);
  592. if (_model.Instance.FormStarted == DateTime.MinValue)
  593. _model.Instance.FormStarted = timeStarted;
  594. _model.Instance.FormOpen += (DateTime.Now - timeStarted);
  595. if (!saveForLater)
  596. {
  597. _model.Instance.FormCompleted = DateTime.Now;
  598. _model.Instance.FormCompletedBy.ID = App.Data.Me.UserID;
  599. _model.Instance.Location.Longitude = location.Longitude;
  600. _model.Instance.Location.Latitude = location.Latitude;
  601. _model.Instance.Location.Timestamp = _model.Instance.FormCompleted;
  602. }
  603. if (deleteform)
  604. _model.Instance.FormCancelled = DateTime.Now;
  605. _model.Update(null);
  606. }
  607. }
  608. #endregion
  609. #region Expressions
  610. public object GetFieldValue(string name)
  611. {
  612. try
  613. {
  614. var definition = Bindings.Keys.FirstOrDefault(x => String.Equals(x.Name, name));
  615. if (definition != null)
  616. return CoreUtils.GetPropertyValue(Bindings[definition],"Value");
  617. }
  618. catch (Exception e)
  619. {
  620. MobileLogging.Log(e,"SetFieldValue");
  621. }
  622. return null;
  623. }
  624. public void SetFieldValue(string name, object value)
  625. {
  626. try
  627. {
  628. var definition = Bindings.Keys.FirstOrDefault(x => String.Equals(x.Name, name));
  629. if (definition != null)
  630. CoreUtils.SetPropertyValue(Bindings[definition],"Value",value);
  631. }
  632. catch (Exception e)
  633. {
  634. MobileLogging.Log(e,"SetFieldValue");
  635. }
  636. }
  637. public object GetFieldData(string fieldName, string dataField)
  638. {
  639. var definition = Bindings.Keys.FirstOrDefault(x => String.Equals(x.Name, fieldName));
  640. if ((definition != null) && (Bindings[definition] is DigitalFormLookupView lookup))
  641. return lookup.OtherValue(dataField);
  642. return null;
  643. }
  644. public void SetFieldColour(string field, System.Drawing.Color? colour = null)
  645. {
  646. if (colour != null)
  647. {
  648. try
  649. {
  650. System.Drawing.Color color = (System.Drawing.Color)colour;
  651. var definition = Bindings.Keys.FirstOrDefault(x => String.Equals(x.Name, field));
  652. if (definition != null)
  653. {
  654. Bindings[definition].BackgroundColor = Color.FromRgba(
  655. Convert.ToDouble(color.R),
  656. Convert.ToDouble(color.G),
  657. Convert.ToDouble(color.B),
  658. Convert.ToDouble(color.A)
  659. );
  660. }
  661. }
  662. catch (Exception e)
  663. {
  664. MobileLogging.Log(e,"SetFieldColor");
  665. }
  666. }
  667. }
  668. #endregion
  669. }
  670. }