DynamicDocumentGrid.cs 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data;
  4. using System.Diagnostics;
  5. using System.Drawing;
  6. using System.Drawing.Printing;
  7. using System.IO;
  8. using System.Linq;
  9. using System.Text.RegularExpressions;
  10. using System.Threading.Tasks;
  11. using System.Windows;
  12. using System.Windows.Controls;
  13. using System.Windows.Data;
  14. using System.Windows.Media;
  15. using System.Windows.Media.Imaging;
  16. using FastReport;
  17. using InABox.Clients;
  18. using InABox.Core;
  19. using InABox.WPF;
  20. using Microsoft.Win32;
  21. using Microsoft.Xaml.Behaviors.Core;
  22. using RoslynPad.Editor;
  23. using Syncfusion.Pdf.Interactive;
  24. using Syncfusion.Pdf.Parsing;
  25. using Syncfusion.Pdf;
  26. using Syncfusion.Windows.PdfViewer;
  27. using Border = System.Windows.Controls.Border;
  28. using Color = System.Windows.Media.Color;
  29. using Image = System.Windows.Controls.Image;
  30. namespace InABox.DynamicGrid
  31. {
  32. public class DocumentConverter : UtilityConverter<object, object>
  33. {
  34. public override object Convert(object value)
  35. {
  36. return value;
  37. }
  38. }
  39. public class TimeStampToBrushConverter : UtilityConverter<DateTime, System.Windows.Media.Brush?>
  40. {
  41. public System.Windows.Media.Brush? Empty { get; init; }
  42. public System.Windows.Media.Brush? Set { get; init; }
  43. public override System.Windows.Media.Brush? Convert(DateTime value)
  44. {
  45. return value.IsEmpty()
  46. ? Empty
  47. : Set;
  48. }
  49. }
  50. public delegate String OnGetWatermark(CoreRow row);
  51. public class DynamicDocumentGrid<TDocument, TEntity, TEntityLink> : DynamicManyToManyGrid<TDocument, TEntity>
  52. where TEntity : Entity, IPersistent, IRemotable, new()
  53. where TDocument : Entity, IEntityDocument<TEntityLink>, IPersistent, IRemotable, new() // Entity, IPersistent, IRemotable, IManyToMany<TEntity, Document>, new()
  54. where TEntityLink : EntityLink<TEntity>, new()
  55. {
  56. // private DynamicActionColumn supercedecolumn;
  57. //
  58. // public bool ShowSupercededColumn
  59. // {
  60. // get
  61. // {
  62. // return supercedecolumn.Position != DynamicActionColumnPosition.Hidden;
  63. // }
  64. // set
  65. // {
  66. // supercedecolumn.Position = value ? DynamicActionColumnPosition.End : DynamicActionColumnPosition.Hidden;
  67. // }
  68. // }
  69. public bool ShowSupercededColumn { get; set; }
  70. private DynamicTemplateColumn _template;
  71. public DynamicDocumentGrid()
  72. {
  73. MultiSelect = false;
  74. HiddenColumns.Add(x => x.DocumentLink.ID);
  75. HiddenColumns.Add(x => x.Superceded);
  76. HiddenColumns.Add(x => x.DocumentLink.FileName);
  77. HiddenColumns.Add(x => x.Thumbnail);
  78. HiddenColumns.Add(x => x.Notes);
  79. //ActionColumns.Add(new DynamicImageColumn(DocumentImage, ViewDocument) { Position = DynamicActionColumnPosition.Start });
  80. //ActionColumns.Add(new DynamicImageColumn(DiskImage, SaveDocument) { Position = DynamicActionColumnPosition.Start });
  81. _template = new DynamicTemplateColumn(DocumentTemplate)
  82. {
  83. Position = DynamicActionColumnPosition.Start,
  84. Width = 0,
  85. HeaderText = "Attached Documents"
  86. };
  87. ActionColumns.Add(_template);
  88. //supercedecolumn = new DynamicImageColumn(SupercededImage, SupercedeDocument);
  89. //ActionColumns.Add(supercedecolumn);
  90. }
  91. protected override void DoDoubleClick(object sender)
  92. {
  93. var doc = SelectedRows.FirstOrDefault()?.ToObject<TDocument>();
  94. if (doc != null)
  95. {
  96. var editor = new DocumentEditor(new IEntityDocument[] { doc });
  97. //editor.PrintAllowed = Security.IsAllowed<CanPrintFactoryFloorDrawings>();
  98. editor.SaveAllowed = false;
  99. editor.ShowDialog();
  100. }
  101. }
  102. private FrameworkElement DocumentTemplate()
  103. {
  104. Border border = new Border()
  105. {
  106. CornerRadius = new CornerRadius(5),
  107. Background = new SolidColorBrush(Colors.WhiteSmoke),
  108. BorderBrush = new SolidColorBrush(Colors.Gray),
  109. BorderThickness = new Thickness(0.75),
  110. Margin = new Thickness(2),
  111. Height = 100,
  112. ContextMenu = new ContextMenu()
  113. };
  114. border.ContextMenu.Items.Add(new MenuItem()
  115. {
  116. Header = "View Documents",
  117. Command = new ActionCommand(ViewDocuments)
  118. });
  119. border.ContextMenu.Items.Add(new MenuItem()
  120. {
  121. Header = "Copy To Clipboard",
  122. Command = new ActionCommand(CopyDocuments)
  123. });
  124. border.ContextMenu.Items.Add(new MenuItem()
  125. {
  126. Header = "Save Documents",
  127. Command = new ActionCommand(SaveDocuments)
  128. });
  129. border.SetBinding(
  130. Border.BackgroundProperty,
  131. new Binding("Superceded")
  132. {
  133. Converter = new TimeStampToBrushConverter()
  134. {
  135. Empty = new SolidColorBrush(Colors.LightYellow),
  136. Set = new SolidColorBrush(Colors.Silver)
  137. }
  138. }
  139. );
  140. Grid grid = new Grid()
  141. {
  142. RowDefinitions =
  143. {
  144. new RowDefinition() { Height = new GridLength(1, GridUnitType.Auto) },
  145. new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) },
  146. },
  147. ColumnDefinitions =
  148. {
  149. new ColumnDefinition() { Width = new GridLength(100) },
  150. new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star) },
  151. new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Auto) },
  152. }
  153. };
  154. border.Child = grid;
  155. Image thumbnail = new Image()
  156. {
  157. Stretch = Stretch.Uniform,
  158. Margin = new Thickness(2,2,5,2),
  159. };
  160. var ttImage = new Image();
  161. ttImage.SetBinding(Image.SourceProperty,
  162. new Binding("Thumbnail") { Converter = new BytesToBitmapImageConverter() });
  163. thumbnail.ToolTip = new ToolTip()
  164. {
  165. Content = ttImage
  166. };
  167. thumbnail.SetBinding(Image.SourceProperty, new Binding("Thumbnail") { Converter = new BytesToBitmapImageConverter() });
  168. thumbnail.SetValue(Grid.RowProperty,0);
  169. thumbnail.SetValue(Grid.RowSpanProperty,2);
  170. thumbnail.SetValue(Grid.ColumnProperty,0);
  171. grid.Children.Add(thumbnail);
  172. var filename = new Label()
  173. {
  174. FontWeight = FontWeights.Bold
  175. };
  176. filename.SetBinding(Label.ContentProperty, new Binding("DocumentLink_FileName"));
  177. filename.SetValue(Grid.RowProperty,0);
  178. filename.SetValue(Grid.ColumnProperty,1);
  179. grid.Children.Add(filename);
  180. var buttons = new StackPanel()
  181. {
  182. Orientation = Orientation.Horizontal
  183. };
  184. buttons.SetValue(Grid.RowProperty,0);
  185. buttons.SetValue(Grid.ColumnProperty,2);
  186. grid.Children.Add(buttons);
  187. var view = new Button()
  188. {
  189. Content = new Image() { Source = Wpf.Resources.multi_image.AsBitmapImage() },
  190. BorderBrush = new SolidColorBrush(Colors.Transparent),
  191. Background = new SolidColorBrush(Colors.Transparent),
  192. Height = 32,
  193. Width = 32,
  194. Command = new ActionCommand(ViewDocuments)
  195. };
  196. buttons.Children.Add(view);
  197. var copy = new Button()
  198. {
  199. Content = new Image() { Source = Wpf.Resources.copy.AsBitmapImage() },
  200. BorderBrush = new SolidColorBrush(Colors.Transparent),
  201. Background = new SolidColorBrush(Colors.Transparent),
  202. Height = 32,
  203. Width = 32,
  204. Command = new ActionCommand(CopyDocuments)
  205. };
  206. buttons.Children.Add(copy);
  207. var save = new Button()
  208. {
  209. Content = new Image() { Source = Wpf.Resources.download.AsBitmapImage() },
  210. BorderBrush = new SolidColorBrush(Colors.Transparent),
  211. Background = new SolidColorBrush(Colors.Transparent),
  212. Height = 32,
  213. Width = 32,
  214. Command = new ActionCommand(SaveDocuments)
  215. };
  216. buttons.Children.Add(save);
  217. var print = new Button()
  218. {
  219. Content = new Image() { Source = Wpf.Resources.print.AsBitmapImage() },
  220. BorderBrush = new SolidColorBrush(Colors.Transparent),
  221. Background = new SolidColorBrush(Colors.Transparent),
  222. Height = 32,
  223. Width = 32,
  224. Command = new ActionCommand(PrintDocuments)
  225. };
  226. buttons.Children.Add(print);
  227. var notes = new Label()
  228. {
  229. };
  230. notes.SetBinding(Label.ContentProperty, new Binding("Notes"));
  231. notes.SetValue(Grid.RowProperty,1);
  232. notes.SetValue(Grid.ColumnProperty,1);
  233. notes.SetValue(Grid.ColumnSpanProperty,2);
  234. grid.Children.Add(notes);
  235. return border;
  236. }
  237. private void GetDocuments(Action<Dictionary<string,byte[]>> action)
  238. {
  239. var ids = SelectedRows.Select(r => r.Get<IEntityDocument, Guid>(c => c.DocumentLink.ID)).ToArray();
  240. var files = new Client<Document>().Query(
  241. new Filter<Document>(x => x.ID).InList(ids),
  242. new Columns<Document>(x => x.FileName).Add(x => x.Data)
  243. ).ToDictionary<Document, String, byte[]>(x => x.FileName, x => x.Data);
  244. action?.Invoke(files);
  245. }
  246. private String SanitiseFileName(string filename)
  247. {
  248. var basefilename = Path.GetFileNameWithoutExtension(filename);
  249. var extension = Path.GetExtension(filename);
  250. return Path.ChangeExtension(string.Join("_", basefilename.Split(Path.GetInvalidFileNameChars())), extension);
  251. }
  252. private void ViewDocuments()
  253. {
  254. GetDocuments((files) =>
  255. {
  256. foreach (var file in files)
  257. {
  258. Task.Run(() =>
  259. {
  260. var tempfile = Path.Combine(System.IO.Path.GetTempPath(), SanitiseFileName(file.Key));
  261. File.WriteAllBytes(tempfile, file.Value);
  262. var info = new System.Diagnostics.ProcessStartInfo(tempfile);
  263. info.UseShellExecute = true;
  264. info.Verb = "Open";
  265. Process.Start(info);
  266. });
  267. }
  268. });
  269. }
  270. private void CopyDocuments()
  271. {
  272. if (SelectedRows?.Any() != true)
  273. return;
  274. GetDocuments((files) =>
  275. {
  276. System.Collections.Specialized.StringCollection FileCollection = new System.Collections.Specialized.StringCollection();
  277. foreach(var file in files)
  278. {
  279. var tempfile = Path.Combine(System.IO.Path.GetTempPath(), SanitiseFileName(file.Key));
  280. File.WriteAllBytes(tempfile, file.Value);
  281. FileCollection.Add(tempfile);
  282. }
  283. Clipboard.SetFileDropList(FileCollection);
  284. });
  285. }
  286. private void SaveDocuments()
  287. {
  288. if (SelectedRows?.Any() != true)
  289. return;
  290. using(var fbd = new System.Windows.Forms.FolderBrowserDialog())
  291. {
  292. var result = fbd.ShowDialog();
  293. if (result == System.Windows.Forms.DialogResult.OK && !string.IsNullOrWhiteSpace(fbd.SelectedPath))
  294. {
  295. var path = fbd.SelectedPath;
  296. GetDocuments(files =>
  297. {
  298. foreach (var file in files)
  299. File.WriteAllBytes(Path.Combine(path, SanitiseFileName(file.Key)), file.Value);
  300. });
  301. }
  302. }
  303. }
  304. private void PrintDocuments()
  305. {
  306. if (SelectedRows?.Any() != true)
  307. return;
  308. GetDocuments(files =>
  309. {
  310. Task.Run(() =>
  311. {
  312. foreach (var file in files)
  313. {
  314. var tempfile = Path.Combine(System.IO.Path.GetTempPath(), SanitiseFileName(file.Key));
  315. File.WriteAllBytes(tempfile, file.Value);
  316. var info = new System.Diagnostics.ProcessStartInfo(tempfile);
  317. info.CreateNoWindow = true;
  318. info.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
  319. info.UseShellExecute = true;
  320. info.Verb = "print";
  321. Process.Start(info);
  322. }
  323. });
  324. });
  325. }
  326. protected override DynamicGridColumns LoadColumns()
  327. {
  328. return new DynamicGridColumns();
  329. }
  330. protected override void DoReconfigure(FluentList<DynamicGridOption> options)
  331. {
  332. base.DoReconfigure(options);
  333. options.Remove(DynamicGridOption.SelectColumns);
  334. options.Add(DynamicGridOption.DragTarget);
  335. }
  336. // private bool SaveDocument(CoreRow? row)
  337. // {
  338. // var filename = row.Get<TDocument, string>(x => x.DocumentLink.FileName);
  339. // if (Path.GetExtension(filename).ToUpper().Equals(".PDF"))
  340. // {
  341. // var dlg = new SaveFileDialog();
  342. // dlg.Filter = "PDF Files (*.pdf)|*.pdf";
  343. // dlg.FileName = Path.ChangeExtension(filename, ".pdf");
  344. // if (dlg.ShowDialog() == true)
  345. // {
  346. // var imageid = row.Get<TDocument, Guid>(x => x.DocumentLink.ID);
  347. // var data = new Client<Document>().Query(new Filter<Document>(x => x.ID).IsEqualTo(imageid)).Rows.FirstOrDefault().Get<Document, byte[]>(x => x.Data);
  348. // var name = dlg.FileName;
  349. // File.WriteAllBytes(name, data);
  350. //
  351. // var gsProcessInfo = new ProcessStartInfo();
  352. // gsProcessInfo.Verb = "open";
  353. // gsProcessInfo.WindowStyle = ProcessWindowStyle.Normal;
  354. // gsProcessInfo.FileName = name;
  355. // gsProcessInfo.UseShellExecute = true;
  356. //
  357. // Process.Start(gsProcessInfo);
  358. // }
  359. //
  360. // }
  361. // else if (Path.GetExtension(filename).ToUpper().Equals(".PNG") || Path.GetExtension(filename).ToUpper().Equals(".JPG") || Path.GetExtension(filename).ToUpper().Equals(".GIF"))
  362. // {
  363. // var imageid = row.Get<TDocument, Guid>(x => x.DocumentLink.ID);
  364. // if (imageid == Guid.Empty)
  365. // return false;
  366. //
  367. // var dlg = new SaveFileDialog();
  368. // dlg.Filter = "Image Files (*.png)|*.png";
  369. // dlg.FileName = filename;
  370. // if (dlg.ShowDialog() == true)
  371. // {
  372. // var bmp = LoadBitmapFromDatabase(imageid);
  373. // bmp?.Save(dlg.FileName);
  374. // }
  375. // }
  376. //
  377. // return false;
  378. // }
  379. //
  380. // private Bitmap LoadBitmapFromDatabase(Guid imageid)
  381. // {
  382. // if (imageid == Guid.Empty)
  383. // return null;
  384. // Bitmap result = null;
  385. // var image = new Client<Document>().Query(
  386. // new Filter<Document>(x => x.ID).IsEqualTo(imageid),
  387. // new Columns<Document>(x => x.ID, x => x.Data)
  388. // ).Rows.FirstOrDefault();
  389. // if (image != null)
  390. // {
  391. // var ms = new MemoryStream(image.Get<Document, byte[]>(x => x.Data));
  392. // result = new Bitmap(ms);
  393. // }
  394. //
  395. // return result;
  396. // }
  397. // private BitmapImage? DiskImage(CoreRow? arg)
  398. // {
  399. // return Wpf.Resources.disk.AsBitmapImage();
  400. // }
  401. public override int Order()
  402. {
  403. return int.MaxValue;
  404. }
  405. // private BitmapImage SupercededImage(CoreRow? row)
  406. // {
  407. // if (row == null)
  408. // return Wpf.Resources.tick.AsBitmapImage();
  409. // if (row.Get<TDocument, DateTime>(x => x.Superceded) != DateTime.MinValue)
  410. // return Wpf.Resources.warning.AsBitmapImage();
  411. // return Wpf.Resources.tick.AsBitmapImage();
  412. // }
  413. //
  414. // private bool SupercedeDocument(CoreRow? row)
  415. // {
  416. // if (!ReadOnly)
  417. // {
  418. // var id = row.Get<TDocument, Guid>(x => x.ID);
  419. // var document = WorkingList.FirstOrDefault(x => x.ID.Equals(id));
  420. // if (document != null)
  421. // document.Superceded = document.Superceded == DateTime.MinValue ? DateTime.Now : DateTime.MinValue;
  422. // return true;
  423. // }
  424. // else
  425. // {
  426. // return false;
  427. // }
  428. // }
  429. //
  430. // private BitmapImage DocumentImage(CoreRow? arg)
  431. // {
  432. // return Wpf.Resources.view.AsBitmapImage();
  433. // }
  434. //
  435. // private bool ViewDocument(CoreRow? row)
  436. // {
  437. // var filename = row.Get<TDocument, string>(x => x.DocumentLink.FileName);
  438. // if (Path.GetExtension(filename).ToUpper().Equals(".PDF"))
  439. // {
  440. // var viewer = new DocumentEditor(row.ToObject<TDocument>());
  441. // viewer.Watermark = OnGetWaterMark?.Invoke(row);
  442. // //viewer.PrintAllowed = true;
  443. // viewer.SaveAllowed = true;
  444. // viewer.ShowDialog();
  445. // }
  446. // else
  447. // {
  448. // var id = row.Get<TDocument, Guid>(x => x.DocumentLink.ID);
  449. // var docrow = new Client<Document>().Query(new Filter<Document>(x => x.ID).IsEqualTo(id)).Rows.FirstOrDefault();
  450. // if (docrow != null)
  451. // {
  452. // var tmpfile = Path.ChangeExtension(Path.GetTempFileName(), Path.GetExtension(filename));
  453. // File.WriteAllBytes(tmpfile, docrow.Get<Document, byte[]>(x => x.Data));
  454. // var gsProcessInfo = new ProcessStartInfo();
  455. // gsProcessInfo.Verb = "open";
  456. // gsProcessInfo.WindowStyle = ProcessWindowStyle.Normal;
  457. // gsProcessInfo.FileName = tmpfile;
  458. // gsProcessInfo.UseShellExecute = true;
  459. //
  460. // Process.Start(gsProcessInfo);
  461. // }
  462. // else
  463. // {
  464. // MessageBox.Show(string.Format("Unable to retrieve {0}!", filename));
  465. // }
  466. // }
  467. //
  468. // //Document doc = new Client<Document>().Load(new Filter<Document>(x => x.ID).IsEqualTo(id)).FirstOrDefault();
  469. // //if (doc != null)
  470. // //{
  471. // // if (System.IO.Path.GetExtension(doc.FileName).ToUpper().Equals(".PDF"))
  472. // // {
  473. // // PDFViewer viewer = new PDFViewer(doc);
  474. // // viewer.ShowDialog();
  475. // // }
  476. // // else
  477. // // {
  478. // // String filename = System.IO.Path.ChangeExtension(System.IO.Path.GetTempFileName(), System.IO.Path.GetExtension(doc.FileName));
  479. // // System.IO.File.WriteAllBytes(filename, doc.Data);
  480. // // ProcessStartInfo gsProcessInfo = new ProcessStartInfo();
  481. // // gsProcessInfo.Verb = "open";
  482. // // gsProcessInfo.WindowStyle = ProcessWindowStyle.Normal;
  483. // // gsProcessInfo.UseShellExecute = true;
  484. // // gsProcessInfo.FileName = filename;
  485. // // Process.Start(gsProcessInfo);
  486. // // }
  487. // //}
  488. // //else
  489. // // MessageBox.Show("Document does nto exist!");
  490. // return false;
  491. // }
  492. public event OnGetWatermark OnGetWaterMark;
  493. protected override void OnDragEnd(Type entity, CoreTable table, DragEventArgs e)
  494. {
  495. if (entity == typeof(Document))
  496. {
  497. var refresh = false;
  498. var docIDS = table.Rows.Select(x => x.Get<Document, Guid>(x => x.ID)).ToArray();
  499. var columns = new Columns<Document>(x => x.ID);
  500. foreach (var column in VisibleColumns)
  501. {
  502. if (column.ColumnName.StartsWith("DocumentLink."))
  503. {
  504. columns.Add(string.Join('.', column.ColumnName.Split('.').Skip(1)));
  505. }
  506. }
  507. var docs = new Client<Document>()
  508. .Query(
  509. new Filter<Document>(x => x.ID).InList(docIDS),
  510. columns);
  511. foreach (var doc in docs.ToObjects<Document>())
  512. {
  513. var entityDocument = new TDocument();
  514. entityDocument.EntityLink.ID = Item.ID;
  515. entityDocument.DocumentLink.ID = doc.ID;
  516. entityDocument.DocumentLink.Synchronise(doc);
  517. SaveItem(entityDocument);
  518. refresh = true;
  519. }
  520. if (refresh)
  521. {
  522. Refresh(false, true);
  523. }
  524. }
  525. else
  526. {
  527. base.OnDragEnd(entity, table, e);
  528. }
  529. }
  530. protected override void DoAdd(bool OpenEditorOnDirectEdit = false)
  531. {
  532. var dlg = new OpenFileDialog();
  533. dlg.Multiselect = true;
  534. if (dlg.ShowDialog() == true)
  535. {
  536. using (new WaitCursor())
  537. {
  538. var docs = new List<Document>();
  539. foreach (var filename in dlg.FileNames)
  540. {
  541. // Create a Document
  542. var doc = new Document();
  543. doc.FileName = Path.GetFileName(filename).ToLower();
  544. doc.TimeStamp = new FileInfo(dlg.FileName).LastWriteTime;
  545. doc.Data = File.ReadAllBytes(filename);
  546. doc.CRC = CoreUtils.CalculateCRC(doc.Data);
  547. docs.Add(doc);
  548. }
  549. if (docs.Any())
  550. {
  551. new Client<Document>().Save(docs, "Initial Upload");
  552. foreach (var doc in docs)
  553. {
  554. var newitem = CreateItem();
  555. var prop = (IEntityLink)otherproperty.GetValue(newitem);
  556. prop.ID = doc.ID;
  557. prop.Synchronise(doc);
  558. SaveItem(newitem);
  559. }
  560. DoChanged();
  561. }
  562. }
  563. Refresh(false, true);
  564. }
  565. }
  566. }
  567. }