PageEditContentViewModel.cs 44 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372
  1. using Prism.Mvvm;
  2. using Prism.Regions;
  3. using Prism.Services.Dialogs;
  4. using System;
  5. using System.Collections.Generic;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Threading.Tasks;
  9. using System.Windows.Media;
  10. using ComPDFKitViewer.PdfViewer;
  11. using PDF_Office.Model;
  12. using System.Collections.ObjectModel;
  13. using PDF_Office.Model.PageEdit;
  14. using Prism.Commands;
  15. using System.Windows;
  16. using System.Windows.Media.Imaging;
  17. using System.Windows.Controls.Primitives;
  18. using System.Diagnostics;
  19. using System.Windows.Controls;
  20. using System.Windows.Threading;
  21. using Prism.Events;
  22. using PDF_Office.EventAggregators;
  23. using System.Windows.Input;
  24. using PDF_Office.Helper;
  25. using Microsoft.Win32;
  26. using ComPDFKit.PDFDocument;
  27. using PDF_Office.CustomControl;
  28. namespace PDF_Office.ViewModels.PageEdit
  29. {
  30. public class PageEditContentViewModel : BindableBase, INavigationAware
  31. {
  32. private CPDFViewer PDFViewer;
  33. private ViewContentViewModel viewContentViewModel;
  34. private IDialogService dialogs;
  35. private IEventAggregator eventor;
  36. /// <summary>
  37. /// 用于筛选多窗体时间的唯一识别码
  38. /// </summary>
  39. private string unicode = null;
  40. /// <summary>
  41. /// Undo操作记录栈
  42. /// 只有插入、移位、旋转,倒序需要记录
  43. /// </summary>
  44. private Stack<PageEditItem> UndoStack = new Stack<PageEditItem>();
  45. /// <summary>
  46. /// Redo操作记录栈
  47. /// </summary>
  48. private Stack<PageEditItem> RedoStack = new Stack<PageEditItem>();
  49. /// <summary>
  50. /// 项数据集合
  51. /// </summary>
  52. public ObservableCollection<PageEditItem> PageEditItems { get; set; }
  53. /// <summary>
  54. /// 页面范围的项集合
  55. /// </summary>
  56. public ObservableCollection<string> PageRangeItems { get; set; }
  57. #region 属性
  58. /// <summary>
  59. /// 是否是第一次加载
  60. /// </summary>
  61. private bool isFirstLoad = true;
  62. /// <summary>
  63. /// 记录多选项中最后一项的索引
  64. /// </summary>
  65. private int maxSelectedIndex = 0;
  66. private Visibility showTip = Visibility.Collapsed;
  67. /// <summary>
  68. /// 是否显示渐隐提示
  69. /// </summary>
  70. public Visibility ShowTip
  71. {
  72. get { return showTip; }
  73. set
  74. {
  75. SetProperty(ref showTip, value);
  76. }
  77. }
  78. private Visibility isLoading = Visibility.Collapsed;
  79. /// <summary>
  80. /// 是否正在处理中
  81. /// </summary>
  82. public Visibility IsLoading
  83. {
  84. get { return isLoading; }
  85. set
  86. {
  87. SetProperty(ref isLoading, value);
  88. }
  89. }
  90. private int listSelecedIndex;
  91. /// <summary>
  92. /// 缩略图选中项的索引
  93. /// </summary>
  94. public int ListSelectedIndex
  95. {
  96. get { return listSelecedIndex; }
  97. set
  98. {
  99. SetProperty(ref listSelecedIndex, value);
  100. //显示页面范围选择控件
  101. TbPageRangeVisibility = Visibility.Visible;
  102. TbPageRange = (ListSelectedIndex + 1).ToString();
  103. TxtPageInputVisibility = Visibility.Collapsed;
  104. if(IsBOTAThumb==Visibility.Visible&&PDFViewer!=null)
  105. {
  106. PDFViewer.GoToPage(listSelecedIndex);
  107. }
  108. }
  109. }
  110. private bool isMutiSelected;
  111. /// <summary>
  112. /// 是否有多选 用于判断倒序和替换功能
  113. /// </summary>
  114. public bool IsMutiSelected
  115. {
  116. get { return isMutiSelected; }
  117. set
  118. {
  119. SetProperty(ref isMutiSelected, value);
  120. }
  121. }
  122. private int comboxSelectIndex;
  123. /// <summary>
  124. /// 下拉框选项集合
  125. /// </summary>
  126. public int ComboxSelectIndex
  127. {
  128. get { return comboxSelectIndex; }
  129. set
  130. {
  131. SetProperty(ref comboxSelectIndex, value);
  132. //选中指定的页面范围
  133. SuitPageRange(comboxSelectIndex);
  134. //隐藏tb页面范围显示控件
  135. TbPageRangeVisibility = Visibility.Collapsed;
  136. }
  137. }
  138. private Visibility tbPageRangeVisibility = Visibility.Visible;
  139. /// <summary>
  140. /// 页面范围的文本显示
  141. /// </summary>
  142. public Visibility TbPageRangeVisibility
  143. {
  144. get { return tbPageRangeVisibility; }
  145. set
  146. {
  147. SetProperty(ref tbPageRangeVisibility, value);
  148. if (value == Visibility.Visible)
  149. {
  150. comboxSelectIndex = -1;
  151. }
  152. }
  153. }
  154. private string tbPageRange;
  155. /// <summary>
  156. /// 页面范围显示的内容
  157. /// </summary>
  158. public string TbPageRange
  159. {
  160. get { return tbPageRange; }
  161. set
  162. {
  163. SetProperty(ref tbPageRange, value);
  164. }
  165. }
  166. private Visibility txtPageInputVisibility = Visibility.Collapsed;
  167. /// <summary>
  168. /// 页面自定义输入框的显示
  169. /// </summary>
  170. public Visibility TxtPageInputVisibility
  171. {
  172. get { return txtPageInputVisibility; }
  173. set
  174. {
  175. SetProperty(ref txtPageInputVisibility, value);
  176. }
  177. }
  178. /// <summary>
  179. /// 页面缩放状态,-1 为最小值,1为最大值
  180. /// </summary>
  181. private int zoomIndex = 0;
  182. public int ZoomIndex
  183. {
  184. get { return zoomIndex; }
  185. set
  186. {
  187. SetProperty(ref zoomIndex, value);
  188. }
  189. }
  190. private string toastText;
  191. /// <summary>
  192. /// Toast提示
  193. /// </summary>
  194. public string ToastText
  195. {
  196. get { return toastText; }
  197. set
  198. {
  199. SetProperty(ref toastText, value);
  200. }
  201. }
  202. private Visibility isBOTAThumb = Visibility.Collapsed;
  203. /// <summary>
  204. /// 是否是BOTA侧边栏的缩略图
  205. /// </summary>
  206. public Visibility IsBOTAThumb
  207. {
  208. get { return isBOTAThumb; }
  209. set
  210. {
  211. SetProperty(ref isBOTAThumb, value);
  212. }
  213. }
  214. #endregion
  215. #region 命令
  216. public DelegateCommand<object> SelectionChangedCommand { get; set; }
  217. /// <summary>
  218. /// 拦截键盘输入的事件
  219. /// </summary>
  220. public DelegateCommand<object> PreviewKeyDown { get; set; }
  221. /// <summary>
  222. /// 响应键盘回车事件
  223. /// </summary>
  224. public DelegateCommand<object> KeyDown { get; set; }
  225. /// <summary>
  226. /// 替换文件
  227. /// </summary>
  228. public DelegateCommand ReplaceCommand { get; set; }
  229. /// <summary>
  230. /// 插入文件命令
  231. /// </summary>
  232. public DelegateCommand<object> InsertCommand { get; set; }
  233. /// <summary>
  234. /// 拆分文件
  235. /// </summary>
  236. public DelegateCommand SplitCommand { get; set; }
  237. /// <summary>
  238. /// 提取文件
  239. /// </summary>
  240. public DelegateCommand ExtractCommand { get; set; }
  241. /// <summary>
  242. /// 逆时针旋转
  243. /// </summary>
  244. public DelegateCommand LeftRotateCommand { get; set; }
  245. /// <summary>
  246. /// 顺时针旋转
  247. /// </summary>
  248. public DelegateCommand RightRotateCommand { get; set; }
  249. /// <summary>
  250. /// 删除
  251. /// </summary>
  252. public DelegateCommand DeleteCommand { get; set; }
  253. /// <summary>
  254. /// 倒序
  255. /// </summary>
  256. public DelegateCommand ReverseCommand { get; set; }
  257. /// <summary>
  258. /// 放大
  259. /// </summary>
  260. public DelegateCommand ZoomInCommand { get; set; }
  261. /// <summary>
  262. /// 缩小
  263. /// </summary>
  264. public DelegateCommand ZoomOutCommand { get; set; }
  265. #endregion
  266. public PageEditContentViewModel(IDialogService dialogService, IEventAggregator eventAggregator)
  267. {
  268. //变量初始化
  269. dialogs = dialogService;
  270. eventor = eventAggregator;
  271. unicode = App.mainWindowViewModel.SelectedItem.Unicode;
  272. PageEditItems = new ObservableCollection<PageEditItem>();
  273. PageRangeItems = new ObservableCollection<string>();
  274. //绑定命令
  275. SelectionChangedCommand = new DelegateCommand<object>(SelectionChangedEvent);
  276. PreviewKeyDown = new DelegateCommand<object>(PreviewKeyDownEvent);
  277. KeyDown = new DelegateCommand<object>(KeyDownEvent);
  278. SplitCommand = new DelegateCommand(SplitCommandEvent);
  279. InsertCommand = new DelegateCommand<object>(InsertCommandEvent);
  280. ReplaceCommand = new DelegateCommand(ReplaceCommandEvent, CanReplaceCommandExcute).ObservesProperty(() => IsMutiSelected);
  281. ExtractCommand = new DelegateCommand(ExtractCommandEvent, CanFileCommandExcute).ObservesProperty(() => ListSelectedIndex);
  282. DeleteCommand = new DelegateCommand(DeleteCommandEvent, CanFileCommandExcute).ObservesProperty(() => ListSelectedIndex);
  283. LeftRotateCommand = new DelegateCommand(LeftRotateCommandEvent, CanFileCommandExcute).ObservesProperty(() => ListSelectedIndex);
  284. RightRotateCommand = new DelegateCommand(RightRotateCommandEvent, CanFileCommandExcute).ObservesProperty(() => ListSelectedIndex);
  285. ReverseCommand = new DelegateCommand(ReverseCommandEvent, CanFileCommandExcute).ObservesProperty(() => ListSelectedIndex);
  286. ZoomInCommand = new DelegateCommand(ZoomInCommandEvent, CanZoomIn).ObservesProperty(() => ZoomIndex);
  287. ZoomOutCommand = new DelegateCommand(ZoomOutCommandEvent, CanZoomOut).ObservesProperty(() => ZoomIndex);
  288. //订阅页面刷新事件
  289. eventAggregator.GetEvent<PageEditRefreshEvent>().Subscribe(OnPageEditRefreshEvent, e => e.Unicode == unicode);
  290. RefreshPageRangeItem();
  291. }
  292. #region 事件
  293. /// <summary>
  294. /// 替换功能的逻辑
  295. /// </summary>
  296. private async void ReplaceCommandEvent()
  297. {
  298. OpenFileDialog dialog = new OpenFileDialog();
  299. dialog.Multiselect = false;
  300. dialog.Filter = PDF_Office.Properties.Resources.OpenDialogFilter;
  301. if ((bool)dialog.ShowDialog())
  302. {
  303. IsLoading = Visibility.Visible;
  304. await Task.Delay(200);
  305. int pageCount = PDFViewer.Document.PageCount;
  306. int insertIndex = listSelecedIndex;
  307. //从文件插入到指定位置
  308. var result = await InsertFromFile(listSelecedIndex+1,dialog.FileName);
  309. if(result)
  310. {
  311. //插入成功后再删除原有页面
  312. DoRemoveSelectedPages(new List<int>() { listSelecedIndex });
  313. }
  314. ReloadAfterOption(true, true, Tuple.Create(insertIndex-1, insertIndex + pageCount));
  315. IsLoading = Visibility.Collapsed;
  316. }
  317. }
  318. /// <summary>
  319. /// 拆分功能的逻辑
  320. /// </summary>
  321. private void SplitCommandEvent()
  322. {
  323. DialogParameters valuePairs = new DialogParameters();
  324. valuePairs.Add(ParameterNames.PDFViewer, PDFViewer);
  325. dialogs.ShowDialog(DialogNames.SplitDialog, valuePairs, null);
  326. }
  327. /// <summary>
  328. /// 提取功能的逻辑
  329. /// </summary>
  330. private void ExtractCommandEvent()
  331. {
  332. dialogs.ShowDialog(DialogNames.ExtractDialog,null,e=> {
  333. if(e.Result==ButtonResult.OK&&e.Parameters!=null)
  334. {
  335. var model = e.Parameters.GetValue<ExtractModel>(ParameterNames.DataModel);
  336. DoExtractPages(model.IsEveryPageToFile,model.IsDeleteAfterExtract);
  337. }
  338. });
  339. }
  340. /// <summary>
  341. /// 插入功能的逻辑
  342. /// </summary>
  343. private async void InsertCommandEvent(object type)
  344. {
  345. if((string)type==null)
  346. {
  347. return;
  348. }
  349. //获取插入位置
  350. int insertIndex = 0;
  351. if(listSelecedIndex<0)
  352. {
  353. insertIndex = 0;
  354. }
  355. else
  356. {
  357. insertIndex = listSelecedIndex+1;
  358. if(isMutiSelected)
  359. {
  360. insertIndex = maxSelectedIndex+1;
  361. }
  362. }
  363. IsLoading = Visibility.Visible;
  364. await Task.Delay(3);
  365. if((string)type==ParameterNames.InsertType_Blank)
  366. {
  367. //插入空白页面
  368. bool result;
  369. if (insertIndex == 0)
  370. {
  371. result = PDFViewer.Document.InsertPage(insertIndex, PageEditItems[insertIndex].Size.Width, PageEditItems[insertIndex].Size.Height, null);
  372. }
  373. else
  374. {
  375. result = PDFViewer.Document.InsertPage(insertIndex, PageEditItems[insertIndex-1].Size.Width, PageEditItems[insertIndex-1].Size.Height, null);
  376. }
  377. if(!result)
  378. {
  379. IsLoading = Visibility.Collapsed;
  380. ShowTip = Visibility.Visible;
  381. return;
  382. }
  383. //UI层插入Item
  384. var item = GetNewPageEditItem(insertIndex);
  385. PageEditItems.Insert(insertIndex,item);
  386. ReloadAfterOption(true,true,Tuple.Create(insertIndex,insertIndex+1));
  387. await Task.Delay(10);
  388. ListSelectedIndex = insertIndex == 0 ? insertIndex : insertIndex;
  389. }
  390. else if((string)type == ParameterNames.InsertType_File)
  391. {
  392. OpenFileDialog dialog = new OpenFileDialog();
  393. dialog.Multiselect = false;
  394. dialog.Filter = PDF_Office.Properties.Resources.OpenDialogFilter;
  395. if ((bool)dialog.ShowDialog())
  396. {
  397. //插入文件
  398. var result = await InsertFromFile(insertIndex,dialog.FileName);
  399. if(!result)
  400. {
  401. IsLoading = Visibility.Collapsed;
  402. ShowTip = Visibility.Visible;
  403. return;
  404. }
  405. ReloadAfterOption(true,true,Tuple.Create(0,PDFViewer.Document.PageCount));
  406. }
  407. }
  408. else
  409. {
  410. //插入自定义页面
  411. dialogs.ShowDialog(DialogNames.InsertDialog, null, null);
  412. }
  413. IsLoading = Visibility.Collapsed;
  414. }
  415. /// <summary>
  416. /// 删除选中页面
  417. /// </summary>
  418. private async void DeleteCommandEvent()
  419. {
  420. IsLoading = Visibility.Visible;
  421. await Task.Delay(3);
  422. DoRemoveSelectedPages();
  423. ReloadAfterOption(true, true, Tuple.Create(0,PDFViewer.Document.PageCount));
  424. IsLoading = Visibility.Collapsed;
  425. }
  426. /// <summary>
  427. /// 左旋转页面的逻辑
  428. /// </summary>
  429. private void LeftRotateCommandEvent()
  430. {
  431. RotateSelectedPages(false);
  432. }
  433. /// <summary>
  434. /// 右旋转页面的逻辑
  435. /// </summary>
  436. private void RightRotateCommandEvent()
  437. {
  438. RotateSelectedPages();
  439. }
  440. /// <summary>
  441. /// 页面倒序的逻辑
  442. /// </summary>
  443. private async void ReverseCommandEvent()
  444. {
  445. IsLoading = Visibility.Visible;
  446. await Task.Delay(3);
  447. List<int> pages = new List<int>();
  448. for (int i = 0; i <PageEditItems.Count; i++)
  449. {
  450. if (PageEditItems[i].Selected)
  451. {
  452. pages.Add(i);
  453. }
  454. }
  455. if(pages.Count<=1)
  456. {
  457. ShowToast("请至少选择两个图片进行倒序操作。");
  458. return;
  459. }
  460. pages.Sort();
  461. for (int i = 0; i < pages.Count; i++)
  462. {
  463. int preindex = pages[i];
  464. int laterIndex = pages[pages.Count - i - 1];//尾部的索引
  465. if (laterIndex <= preindex)//交换完成
  466. {
  467. break;
  468. }
  469. var sourceitem = PageEditItems[preindex];
  470. var targetitem = PageEditItems[laterIndex];
  471. var result = PDFViewer.Document.ExchangePage(preindex, laterIndex);
  472. if(!result)
  473. {
  474. ShowTip = Visibility.Visible;
  475. IsLoading = Visibility.Collapsed;
  476. return;
  477. }
  478. PageEditItems.Remove(sourceitem);
  479. PageEditItems.Remove(targetitem);
  480. PageEditItems.Insert(preindex, targetitem);
  481. PageEditItems.Insert(laterIndex, sourceitem);
  482. }
  483. await Task.Delay(20);
  484. for(int i=0;i<pages.Count;i++)
  485. {
  486. PageEditItems[i].Selected = true;
  487. }
  488. ReloadAfterOption(true,true,null);
  489. IsLoading = Visibility.Collapsed;
  490. }
  491. /// <summary>
  492. /// 是否可以执行文件操作命令 除插入、拆分外
  493. /// </summary>
  494. /// <returns></returns>
  495. private bool CanFileCommandExcute()
  496. {
  497. if (ListSelectedIndex < 0)
  498. {
  499. return false;
  500. }
  501. else
  502. {
  503. return true;
  504. }
  505. }
  506. /// <summary>
  507. /// 校验是否可以替换
  508. /// </summary>
  509. /// <returns></returns>
  510. private bool CanReplaceCommandExcute()
  511. {
  512. return !IsMutiSelected;
  513. }
  514. /// <summary>
  515. /// 放大页面
  516. /// </summary>
  517. private void ZoomInCommandEvent()
  518. {
  519. ChangeItemSize(new Size(PageEditItems[0].ItemSize.Width *2, PageEditItems[0].ItemSize.Height *2));
  520. ZoomIndex++;
  521. NotifyUIToRefresh();
  522. }
  523. /// <summary>
  524. /// 缩小页面
  525. /// </summary>
  526. private void ZoomOutCommandEvent()
  527. {
  528. ChangeItemSize(new Size(PageEditItems[0].ItemSize.Width / 2, PageEditItems[0].ItemSize.Height / 2));
  529. ZoomIndex--;
  530. NotifyUIToRefresh();
  531. }
  532. /// <summary>
  533. ///
  534. /// </summary>
  535. /// <param name="newsize"></param>
  536. public void ChangeItemSize(Size newsize)
  537. {
  538. for (int i = 0; i < PageEditItems.Count; i++)
  539. {
  540. PageEditItems[i].ItemSize = newsize;
  541. }
  542. }
  543. private bool CanZoomIn()
  544. {
  545. if (ZoomIndex >= 1)
  546. {
  547. return false;
  548. }
  549. else
  550. {
  551. return true;
  552. }
  553. }
  554. private bool CanZoomOut()
  555. {
  556. if (ZoomIndex <= -1)
  557. {
  558. return false;
  559. }
  560. else
  561. {
  562. return true;
  563. }
  564. }
  565. /// <summary>
  566. /// 响应UI发送刷新图片的事件
  567. /// </summary>
  568. /// <param name="e"></param>
  569. private void OnPageEditRefreshEvent(PageEditRefreshEventArgs e)
  570. {
  571. //UI发送事件过来通知刷新图片时
  572. //调整逻辑,前后预加载5页
  573. RefreshItemImage(e.PageRange.Item1 - 2, e.PageRange.Item2 + 2);
  574. }
  575. /// <summary>
  576. /// 选项改变事件
  577. /// 虚拟化的时候不会触发选中事件
  578. /// </summary>
  579. /// <param name="e"></param>
  580. private void SelectionChangedEvent(object e)
  581. {
  582. //var args = e as SelectionChangedEventArgs;
  583. //var listbox = args.OriginalSource as ListBox;
  584. //if (TbPageRangeVisibility == Visibility.Visible && args != null)
  585. //{
  586. // List<int> pagelist = new List<int>();
  587. // for (int i = 0; i < listbox.SelectedItems.Count; i++)
  588. // {
  589. // if (!pagelist.Contains((listbox.SelectedItems[i] as PageEditItem).PageNumber))
  590. // {
  591. // pagelist.Add((listbox.SelectedItems[i] as PageEditItem).PageNumber);
  592. // }
  593. // }
  594. // ////手动取消其他项的选中状态
  595. // //for (int j = 0; j < PageEditItems.Count; j++)
  596. // //{
  597. // // if (!pagelist.Contains(PageEditItems[j].PageNumber))
  598. // // {
  599. // // PageEditItems[j].Selected = false;
  600. // // }
  601. // //}
  602. // ////根据选中的范围 适配全部页面范围、奇数页面范围等
  603. // //if(pagelist.Count==PageEditItems.Count)
  604. // //{
  605. // // ComboxSelectIndex = 0;
  606. // // return;
  607. // //}
  608. // string pageparm = CommonHelper.GetPageParmFromList(pagelist);
  609. // TbPageRange = pageparm;
  610. //}
  611. //if (listbox.SelectedItem != null)
  612. //{
  613. // listbox.ScrollIntoView(listbox.SelectedItem);
  614. //}
  615. ////判断是否有选中多项
  616. //if (listbox.SelectedItems.Count > 1)
  617. //{
  618. // IsMutiSelected = true;
  619. // maxSelectedIndex = listbox.Items.IndexOf(listbox.SelectedItems[listbox.SelectedItems.Count-1]);
  620. //}
  621. //else
  622. //{
  623. // IsMutiSelected = false;
  624. //}
  625. }
  626. /// <summary>
  627. /// 限制文本框输入内容
  628. /// </summary>
  629. /// <param name="e"></param>
  630. private void PreviewKeyDownEvent(object e)
  631. {
  632. var args = e as KeyEventArgs;
  633. if (args == null)
  634. {
  635. return;
  636. }
  637. if (args.Key != Key.Enter && args.Key != Key.Back && args.Key != Key.OemComma && args.Key != Key.Subtract && !((args.Key >= Key.D0 && args.Key <= Key.D9) || (args.Key >= Key.NumPad0 && args.Key <= Key.NumPad9)))
  638. {
  639. args.Handled = true;
  640. }
  641. }
  642. /// <summary>
  643. /// 响应回车确认事件
  644. /// </summary>
  645. /// <param name="e"></param>
  646. private void KeyDownEvent(object e)
  647. {
  648. var args = e as KeyEventArgs;
  649. if (args == null)
  650. {
  651. return;
  652. }
  653. if (args.Key == Key.Enter)
  654. {
  655. List<int> TargetPageIndexs = new List<int>();
  656. var result = CommonHelper.GetPagesInRange(ref TargetPageIndexs, (args.OriginalSource as TextBox).Text, PDFViewer.Document.PageCount, new char[] { ',', ',' }, new char[] { '-' });
  657. if (!result)
  658. {
  659. AlertsMessage alertsMessage = new AlertsMessage();
  660. alertsMessage.ShowDialog("","请输入有效范围","OK");
  661. return;
  662. }
  663. //选中输入的页面范围
  664. for (int i = 0; i < PageEditItems.Count; i++)
  665. {
  666. if (TargetPageIndexs.Contains(PageEditItems[i].PageNumber - 1))
  667. {
  668. PageEditItems[i].Selected = true;
  669. }
  670. else
  671. {
  672. PageEditItems[i].Selected = false;
  673. }
  674. }
  675. }
  676. }
  677. #endregion
  678. #region 方法
  679. /// <summary>
  680. /// 退出页面编辑面试,回到阅读页
  681. /// </summary>
  682. public void BackToPDFViewer(int PageIndex)
  683. {
  684. PDFViewer.GoToPage(PageIndex);
  685. viewContentViewModel.ExitToolMode();
  686. }
  687. /// <summary>
  688. /// 显示Toast提示
  689. /// </summary>
  690. private void ShowToast(string content)
  691. {
  692. if (!string.IsNullOrEmpty(content))
  693. {
  694. ToastText = content;
  695. }
  696. else
  697. {
  698. ToastText = "操作失败";
  699. }
  700. ShowTip = Visibility.Visible;
  701. }
  702. /// <summary>
  703. /// 通知UI刷新页面范围
  704. /// 或通过xaml来设置选中项
  705. /// </summary>vb nmjvcx
  706. private void NotifyUIToRefresh(List<int> pageRange=null)
  707. {
  708. if (pageRange == null || pageRange.Count <= 0)
  709. {
  710. //通知UI刷新页面范围
  711. eventor.GetEvent<PageEditNotifyEvent>().Publish(new PageEditNotifyEventArgs(unicode));
  712. }
  713. else
  714. {
  715. //通知UI刷新页面范围
  716. eventor.GetEvent<PageEditNotifyEvent>().Publish(new PageEditNotifyEventArgs(unicode,NotifyType.SelectItems,pageRange));
  717. }
  718. }
  719. /// <summary>
  720. /// 删除选中项的方法 不带Reload操作
  721. /// 方便其他逻辑中调用
  722. /// </summary>
  723. private void DoRemoveSelectedPages(List<int> pageList = null)
  724. {
  725. List<int> indexList = new List<int>();
  726. if (pageList == null || pageList.Count < 0)
  727. {
  728. for (int i = 0; i < PageEditItems.Count; i++)
  729. {
  730. if (PageEditItems[i].Selected)
  731. {
  732. indexList.Add(i);
  733. }
  734. }
  735. }
  736. else
  737. {
  738. indexList = pageList;
  739. }
  740. if(indexList.Count>0&& indexList.Count==PDFViewer.Document.PageCount)
  741. {
  742. AlertsMessage alertsMessage = new AlertsMessage();
  743. alertsMessage.ShowDialog("","不能删除所有页面","OK");
  744. return;
  745. }
  746. var result = PDFViewer.Document.RemovePages(indexList.ToArray());
  747. if (!result)
  748. {
  749. ShowTip = Visibility.Visible;
  750. return;
  751. }
  752. //文档层操作成功后再删除UI层
  753. for (int i = indexList.Count - 1; i >= 0; i--)
  754. {
  755. PageEditItems.RemoveAt(indexList[i]);
  756. }
  757. }
  758. /// <summary>
  759. /// 提取选中页面的方法
  760. /// </summary>
  761. /// <param name="isEveryPageToFile">是否每页生成一个文件</param>
  762. /// <param name="isDeleteAfterExtract">是否提取后删除页面</param>
  763. private async void DoExtractPages(bool isEveryPageToFile,bool isDeleteAfterExtract)
  764. {
  765. System.Windows.Forms.FolderBrowserDialog dialog = new System.Windows.Forms.FolderBrowserDialog();
  766. if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
  767. {
  768. if (string.IsNullOrEmpty(dialog.SelectedPath))
  769. {
  770. AlertsMessage alertsMessage = new AlertsMessage();
  771. alertsMessage.ShowDialog("","","OK");//补充提示文案
  772. return;
  773. }
  774. }
  775. else
  776. return;
  777. string selectedfile = "";
  778. IsLoading = Visibility.Visible;
  779. await Task.Delay(3);
  780. List<int> pagenums = new List<int>();
  781. for(int i=0;i<PageEditItems.Count;i++)
  782. {
  783. if(PageEditItems[i].Selected)
  784. {
  785. pagenums.Add(PageEditItems[i].PageNumber);
  786. }
  787. }
  788. if (isEveryPageToFile)
  789. {
  790. //每页生成的单独的文件
  791. for (int i = 0; i < pagenums.Count; i++)
  792. {
  793. string filename = PDFViewer.Document.FileName + " " + pagenums[i] + ".pdf";
  794. string path = System.IO.Path.Combine(dialog.SelectedPath, filename);
  795. path = CommonHelper.CreateFilePath(path);
  796. selectedfile = path;
  797. CPDFDocument savedoc = CPDFDocument.CreateDocument();
  798. bool result = savedoc.ImportPages(PDFViewer.Document, pagenums[i].ToString());
  799. if (!result)
  800. {
  801. savedoc.Release();
  802. continue;
  803. }
  804. result = savedoc.WriteToFilePath(path);
  805. if (!result)
  806. {
  807. savedoc.Release();
  808. continue;
  809. }
  810. savedoc.Release();//释放内存
  811. }
  812. }
  813. else//全部生成一个文件
  814. {
  815. string filename = PDFViewer.Document.FileName + " " + CommonHelper.GetPageParmFromList(pagenums) + ".pdf";
  816. string path = System.IO.Path.Combine(dialog.SelectedPath, filename);
  817. path = CommonHelper.CreateFilePath(path);
  818. selectedfile = path;
  819. CPDFDocument savedoc = CPDFDocument.CreateDocument();
  820. string range = String.Join(",", pagenums);
  821. bool result = savedoc.ImportPages(PDFViewer.Document, range);
  822. if (!result)
  823. {
  824. ShowTip = Visibility.Visible;
  825. IsLoading = Visibility.Collapsed;
  826. return;
  827. }
  828. result = savedoc.WriteToFilePath(path);
  829. if (!result)
  830. {
  831. ShowTip = Visibility.Visible;
  832. }
  833. savedoc.Release();//释放内存
  834. }
  835. if(isDeleteAfterExtract)
  836. {
  837. DoRemoveSelectedPages();
  838. ReloadAfterOption(true,true,Tuple.Create(0,PDFViewer.Document.PageCount));
  839. }
  840. CommonHelper.ShowFileBrowser(selectedfile);
  841. IsLoading = Visibility.Collapsed;
  842. }
  843. /// <summary>
  844. /// 将文件插入到指定位置
  845. /// </summary>
  846. /// <param name="insertIndex"></param>
  847. private async Task<bool> InsertFromFile(int insertIndex,string filePath)
  848. {
  849. CPDFDocument doc = CPDFDocument.InitWithFilePath(filePath);
  850. if (doc == null)
  851. {
  852. showTip = Visibility.Visible;
  853. return false;
  854. }
  855. if (doc.IsLocked)
  856. {
  857. DialogParameters value = new DialogParameters();
  858. value.Add(ParameterNames.PDFDocument, doc);
  859. bool result = true;
  860. dialogs.ShowDialog(DialogNames.VerifyPassWordDialog, value,e=>
  861. {
  862. if (e.Result != ButtonResult.OK)
  863. {
  864. result = false;
  865. }
  866. });
  867. if(!result)
  868. {
  869. return false;
  870. }
  871. }
  872. int pageCount = doc.PageCount;
  873. //插入整个新文档
  874. //文档层插入
  875. await Task.Run(() =>
  876. {
  877. var result = PDFViewer.Document.ImportPagesAtIndex(doc, "1-" + pageCount, insertIndex);
  878. if (!result)
  879. {
  880. ShowTip = Visibility.Visible;
  881. return false;
  882. }
  883. //插入成功后释放临时Document对象
  884. doc.Release();
  885. return true;
  886. });
  887. //UI层插入
  888. for (int i = 0; i < pageCount; i++)
  889. {
  890. var item = GetNewPageEditItem(i);
  891. PageEditItems.Insert(insertIndex + i, item);
  892. }
  893. //加一点延时才能显示选中效果
  894. await Task.Delay(400);
  895. for (int i = 0; i < pageCount; i++)
  896. {
  897. PageEditItems[insertIndex + i].Selected = true;
  898. }
  899. return true;
  900. }
  901. /// <summary>
  902. /// 根据索引创建新的Item
  903. /// </summary>
  904. /// <param name="index"></param>
  905. /// <returns></returns>
  906. private PageEditItem GetNewPageEditItem(int index)
  907. {
  908. PageEditItem item = new PageEditItem();
  909. if (PDFViewer.Document.PageAtIndex(index).Rotation % 2 != 0)
  910. {
  911. ///标记为横向页面
  912. item.isVertical = false;
  913. }
  914. item.PageNumber = index + 1;
  915. var pagesize = PDFViewer.Document.GetPageSize(index);
  916. item.Size = pagesize;
  917. item.PageSize = $"{pagesize.Width}mm*{pagesize.Height} mm";
  918. return item;
  919. }
  920. /// <summary>
  921. /// 进行文件操作后刷新PDFView
  922. /// 清除undo 栈
  923. /// 重加载Document
  924. /// 设置保存状态
  925. /// </summary>
  926. /// <param name="needRefreshPageNum">是否需要刷新页码</param>
  927. /// <param name="needClearUndoHistory">是否需要清空注释Undo栈</param>
  928. /// <param name="pageRange">需要刷新的页面范围图片</param>
  929. private void ReloadAfterOption(bool needRefreshPageNum = false, bool needClearUndoHistory = true, Tuple<int, int> pageRange = null)
  930. {
  931. if (needRefreshPageNum)
  932. {
  933. RefreshPageNum();
  934. }
  935. if (needClearUndoHistory)
  936. {
  937. PDFViewer.UndoManager.ClearHistory();
  938. }
  939. if (pageRange != null)
  940. {
  941. if (pageRange.Item2 - pageRange.Item1 > 30)
  942. {
  943. //范围较大时,通知UI获取更准确的刷新范围
  944. NotifyUIToRefresh();
  945. }
  946. else
  947. {
  948. RefreshItemImage(pageRange.Item1, pageRange.Item2);
  949. }
  950. }
  951. PDFViewer.UndoManager.CanSave = true;
  952. PDFViewer.ReloadDocument();
  953. }
  954. /// <summary>
  955. /// 旋转所有选中页面
  956. /// </summary>
  957. /// <param name="rightRotate"></param>
  958. private async void RotateSelectedPages(bool rightRotate = true)
  959. {
  960. IsLoading = Visibility.Visible;
  961. await Task.Delay(2);
  962. for (int i = 0; i < PageEditItems.Count; i++)
  963. {
  964. if (PageEditItems[i].Selected)
  965. {
  966. //逆时针旋转传 - 1 顺时针旋转传1
  967. PDFViewer.Document.RotatePage(i, rightRotate ? 1 : -1);
  968. PDFViewer.Document.ReleasePages(i);
  969. //重新拿图
  970. PageEditItems[i].isVertical = !PageEditItems[i].isVertical;
  971. PageEditItems[i].IsGetImage = false;
  972. }
  973. }
  974. ReloadAfterOption(false, true, Tuple.Create(0, PageEditItems.Count));
  975. IsLoading = Visibility.Collapsed;
  976. }
  977. /// <summary>
  978. /// 刷新页码
  979. /// </summary>
  980. private void RefreshPageNum()
  981. {
  982. for (int i = 0; i < PageEditItems.Count; i++)
  983. {
  984. PageEditItems[i].PageNumber = i + 1;
  985. }
  986. }
  987. /// <summary>
  988. /// 刷新页面范围下拉框
  989. /// </summary>
  990. private void RefreshPageRangeItem()
  991. {
  992. PageRangeItems.Clear();
  993. PageRangeItems.Add("所有页面");
  994. PageRangeItems.Add("奇数页");
  995. PageRangeItems.Add("偶数页");
  996. PageRangeItems.Add("横向页面");
  997. PageRangeItems.Add("纵向页面");
  998. PageRangeItems.Add("自定义");
  999. }
  1000. /// <summary>
  1001. /// 选中目标页面范围的页面
  1002. /// </summary>
  1003. /// <param name="index">页面范围选中项索引</param>
  1004. private void SuitPageRange(int index)
  1005. {
  1006. switch (index)
  1007. {
  1008. case 0:
  1009. for (int i = 0; i < PageEditItems.Count; i++)
  1010. {
  1011. PageEditItems[i].Selected = true;
  1012. }
  1013. break;
  1014. case 1:
  1015. //奇数页
  1016. for (int i = 0; i < PageEditItems.Count; i++)
  1017. {
  1018. if (i % 2 == 0)
  1019. {
  1020. PageEditItems[i].Selected = true;
  1021. }
  1022. else
  1023. {
  1024. PageEditItems[i].Selected = false;
  1025. }
  1026. }
  1027. break;
  1028. case 2:
  1029. //偶数页
  1030. for (int i = 0; i < PageEditItems.Count; i++)
  1031. {
  1032. if (i % 2 == 0)
  1033. {
  1034. PageEditItems[i].Selected = false;
  1035. }
  1036. else
  1037. {
  1038. PageEditItems[i].Selected = true;
  1039. }
  1040. }
  1041. break;
  1042. case 3://横向页面
  1043. for (int i = 0; i < PageEditItems.Count; i++)
  1044. {
  1045. if (PDFViewer.Document.PageAtIndex(i).Rotation % 2 == 0)
  1046. {
  1047. PageEditItems[i].Selected = false;
  1048. }
  1049. else
  1050. {
  1051. PageEditItems[i].Selected = true;
  1052. }
  1053. }
  1054. break;
  1055. case 4://纵向页面
  1056. for (int i = 0; i < PageEditItems.Count; i++)
  1057. {
  1058. if (PDFViewer.Document.PageAtIndex(i).Rotation % 2 == 0)
  1059. {
  1060. PageEditItems[i].Selected = true;
  1061. }
  1062. else
  1063. {
  1064. PageEditItems[i].Selected = false;
  1065. }
  1066. }
  1067. break;
  1068. case 5://自定义
  1069. //取消所有选中
  1070. ListSelectedIndex = -1;
  1071. TxtPageInputVisibility = Visibility.Visible;
  1072. break;
  1073. default:
  1074. break;
  1075. }
  1076. }
  1077. /// <summary>
  1078. /// 是否显示页面尺寸
  1079. /// </summary>
  1080. /// <param name="show">是或否</param>
  1081. private void ShowPageSize(bool show = true)
  1082. {
  1083. for (int i = 0; i < PageEditItems.Count; i++)
  1084. {
  1085. PageEditItems[i].ShowPageSize = show;
  1086. }
  1087. }
  1088. /// <summary>
  1089. /// 从PDFView获取所有Items集合
  1090. /// </summary>
  1091. private void GetSourceItems(bool isFirstLoad)
  1092. {
  1093. if (isFirstLoad||IsBOTAThumb==Visibility.Visible)
  1094. {
  1095. PageEditItems.Clear();
  1096. for (int i = 0; i < PDFViewer.Document.PageCount; i++)
  1097. {
  1098. var item = GetNewPageEditItem(i);
  1099. PageEditItems.Add(item);
  1100. }
  1101. }
  1102. else
  1103. {
  1104. //后续进来仅刷新图片即可
  1105. for (int i = 0; i < PageEditItems.Count; i++)
  1106. {
  1107. PageEditItems[i].IsGetImage = false;
  1108. }
  1109. }
  1110. }
  1111. /// <summary>
  1112. /// 刷新书签列表
  1113. /// </summary>
  1114. public void RefreshBookMarkList()
  1115. {
  1116. if (PDFViewer != null)
  1117. {
  1118. var booklist = PDFViewer.Document.GetBookmarkList();
  1119. if (booklist == null)
  1120. {
  1121. return;
  1122. }
  1123. //获取所有书签的Index集合
  1124. List<int> marks = new List<int>();
  1125. for (int i = 0; i < booklist.Count; i++)
  1126. {
  1127. marks.Add(booklist[i].PageIndex);
  1128. }
  1129. //不能只遍历marks集合,考虑书签集合元素删除的情况
  1130. for (int k = 0; k < PageEditItems.Count; k++)
  1131. {
  1132. if (marks.Contains(k))
  1133. PageEditItems[k].HaveBookMark = true;
  1134. else
  1135. PageEditItems[k].HaveBookMark = false;
  1136. }
  1137. }
  1138. }
  1139. /// <summary>
  1140. /// 刷新指定范围的图片
  1141. /// </summary>
  1142. /// <param name="startIndex"></param>
  1143. /// <param name="endIndex"></param>
  1144. private async void RefreshItemImage(int startIndex, int endIndex)
  1145. {
  1146. for (int i = startIndex; i <= endIndex; i++)
  1147. {
  1148. if (i <= PDFViewer.Document.PageCount - 1 && i >= 0 && PageEditItems.Count > 0)
  1149. {
  1150. //宽高为样式中图片控件宽高
  1151. if (PageEditItems[i].isVertical)
  1152. {
  1153. await PDFViewer.GetThumbnail(i, 208, 294);
  1154. }
  1155. else
  1156. {
  1157. //获取横图
  1158. await PDFViewer.GetThumbnail(i, 294, 208);
  1159. }
  1160. }
  1161. }
  1162. }
  1163. /// <summary>
  1164. /// 从底层库获取对应页面的图片
  1165. /// </summary>
  1166. /// <param name="pageIndex"></param>
  1167. /// <param name="thumb"></param>
  1168. /// <param name="w"></param>
  1169. /// <param name="h"></param>
  1170. private void PDFViewer_OnThumbnailGenerated(int pageIndex, byte[] thumb, int w, int h)
  1171. {
  1172. try
  1173. {
  1174. if (PageEditItems.Count >= pageIndex + 1)
  1175. {
  1176. PixelFormat fmt = PixelFormats.Bgra32;
  1177. BitmapSource bps = BitmapSource.Create(w, h, 96.0, 96.0, fmt, null, thumb, (w * fmt.BitsPerPixel + 7) / 8);
  1178. PageEditItems[pageIndex].Image = bps;
  1179. PageEditItems[pageIndex].IsGetImage = true;
  1180. }
  1181. }
  1182. catch
  1183. {
  1184. }
  1185. }
  1186. #endregion
  1187. #region Navigate
  1188. public bool IsNavigationTarget(NavigationContext navigationContext)
  1189. {
  1190. return true;
  1191. }
  1192. public void OnNavigatedFrom(NavigationContext navigationContext)
  1193. {
  1194. }
  1195. /// <summary>
  1196. /// 从其他页面导航过来的时候会触发
  1197. /// 考虑只有在页面编辑的时候会进行页面的删减,可以尝试逻辑优化:仅第一次进入页面编辑时重新刷新页面
  1198. /// </summary>
  1199. /// <param name="navigationContext"></param>
  1200. public void OnNavigatedTo(NavigationContext navigationContext)
  1201. {
  1202. navigationContext.Parameters.TryGetValue<ViewContentViewModel>(ParameterNames.ViewContentViewModel, out viewContentViewModel);
  1203. navigationContext.Parameters.TryGetValue<CPDFViewer>(ParameterNames.PDFViewer, out PDFViewer);
  1204. bool isBOTA = false;
  1205. navigationContext.Parameters.TryGetValue<bool>(ParameterNames.BOTAThumb, out isBOTA);
  1206. if (PDFViewer != null)
  1207. {
  1208. if (isFirstLoad)
  1209. {
  1210. PDFViewer.OnThumbnailGenerated += PDFViewer_OnThumbnailGenerated;
  1211. PDFViewer.InfoChanged += PDFViewer_InfoChanged;
  1212. ZoomIndex = 0;
  1213. }
  1214. //BOTA缩略图时,显示不同的菜单栏
  1215. if(isBOTA)
  1216. {
  1217. IsBOTAThumb = Visibility.Visible;
  1218. }
  1219. GetSourceItems(isFirstLoad);
  1220. ListSelectedIndex = PDFViewer.CurrentIndex;
  1221. RefreshBookMarkList();
  1222. isFirstLoad = false;
  1223. }
  1224. }
  1225. private void PDFViewer_InfoChanged(object sender, KeyValuePair<string, object> e)
  1226. {
  1227. if(e.Key== "PageNum")
  1228. {
  1229. NotifyUIToRefresh(new List<int> { (int)e.Value});
  1230. }
  1231. }
  1232. #endregion
  1233. }
  1234. }