PageEditContentViewModel.cs 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002
  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. namespace PDF_Office.ViewModels.PageEdit
  28. {
  29. public class PageEditContentViewModel : BindableBase, INavigationAware
  30. {
  31. private CPDFViewer PDFViewer;
  32. private ViewContentViewModel viewContentViewModel;
  33. private IDialogService dialogs;
  34. private IEventAggregator eventor;
  35. private string unicode = null;
  36. /// <summary>
  37. /// 项数据集合
  38. /// </summary>
  39. public ObservableCollection<PageEditItem> PageEditItems { get; set; }
  40. /// <summary>
  41. /// 页面范围的项集合
  42. /// </summary>
  43. public ObservableCollection<string> PageRangeItems { get; set; }
  44. #region 属性
  45. /// <summary>
  46. /// 是否是第一次加载
  47. /// </summary>
  48. private bool isFirstLoad = true;
  49. private Visibility showTip = Visibility.Collapsed;
  50. /// <summary>
  51. /// 是否显示渐隐提示
  52. /// </summary>
  53. public Visibility ShowTip
  54. {
  55. get { return showTip; }
  56. set
  57. {
  58. SetProperty(ref showTip, value);
  59. }
  60. }
  61. private Visibility isLoading = Visibility.Collapsed;
  62. /// <summary>
  63. /// 是否正在处理中
  64. /// </summary>
  65. public Visibility IsLoading
  66. {
  67. get { return isLoading; }
  68. set
  69. {
  70. SetProperty(ref isLoading, value);
  71. }
  72. }
  73. private int listSelecedIndex;
  74. /// <summary>
  75. /// 缩略图选中项的索引
  76. /// </summary>
  77. public int ListSelectedIndex
  78. {
  79. get { return listSelecedIndex; }
  80. set
  81. {
  82. SetProperty(ref listSelecedIndex, value);
  83. //显示页面范围选择控件
  84. TbPageRangeVisibility = Visibility.Visible;
  85. TbPageRange = (ListSelectedIndex + 1).ToString();
  86. TxtPageInputVisibility = Visibility.Collapsed;
  87. }
  88. }
  89. private bool isMutiSelected;
  90. /// <summary>
  91. /// 是否有多选 用于判断倒序和替换功能
  92. /// </summary>
  93. public bool IsMutiSelected
  94. {
  95. get { return isMutiSelected; }
  96. set
  97. {
  98. SetProperty(ref isMutiSelected, value);
  99. }
  100. }
  101. private int comboxSelectIndex;
  102. /// <summary>
  103. /// 下拉框选项集合
  104. /// </summary>
  105. public int ComboxSelectIndex
  106. {
  107. get { return comboxSelectIndex; }
  108. set
  109. {
  110. SetProperty(ref comboxSelectIndex, value);
  111. //选中指定的页面范围
  112. SuitPageRange(comboxSelectIndex);
  113. //隐藏tb页面范围显示控件
  114. TbPageRangeVisibility = Visibility.Collapsed;
  115. }
  116. }
  117. private Visibility tbPageRangeVisibility = Visibility.Visible;
  118. /// <summary>
  119. /// 页面范围的文本显示
  120. /// </summary>
  121. public Visibility TbPageRangeVisibility
  122. {
  123. get { return tbPageRangeVisibility; }
  124. set
  125. {
  126. SetProperty(ref tbPageRangeVisibility, value);
  127. if (value == Visibility.Visible)
  128. {
  129. comboxSelectIndex = -1;
  130. }
  131. }
  132. }
  133. private string tbPageRange;
  134. /// <summary>
  135. /// 页面范围显示的内容
  136. /// </summary>
  137. public string TbPageRange
  138. {
  139. get { return tbPageRange; }
  140. set
  141. {
  142. SetProperty(ref tbPageRange, value);
  143. }
  144. }
  145. private Visibility txtPageInputVisibility = Visibility.Collapsed;
  146. /// <summary>
  147. /// 页面自定义输入框的显示
  148. /// </summary>
  149. public Visibility TxtPageInputVisibility
  150. {
  151. get { return txtPageInputVisibility; }
  152. set
  153. {
  154. SetProperty(ref txtPageInputVisibility, value);
  155. }
  156. }
  157. /// <summary>
  158. /// 页面缩放状态,-1 为最小值,1为最大值
  159. /// </summary>
  160. private int zoomIndex = 0;
  161. public int ZoomIndex
  162. {
  163. get { return zoomIndex; }
  164. set
  165. {
  166. SetProperty(ref zoomIndex, value);
  167. }
  168. }
  169. #endregion
  170. #region 命令
  171. public DelegateCommand<object> SelectionChangedCommand { get; set; }
  172. /// <summary>
  173. /// 拦截键盘输入的事件
  174. /// </summary>
  175. public DelegateCommand<object> PreviewKeyDown { get; set; }
  176. /// <summary>
  177. /// 响应键盘回车事件
  178. /// </summary>
  179. public DelegateCommand<object> KeyDown { get; set; }
  180. /// <summary>
  181. /// 替换文件
  182. /// </summary>
  183. public DelegateCommand ReplaceCommand { get; set; }
  184. /// <summary>
  185. /// 插入文件命令
  186. /// </summary>
  187. public DelegateCommand InsertCommand { get; set; }
  188. /// <summary>
  189. /// 拆分文件
  190. /// </summary>
  191. public DelegateCommand SplitCommand { get; set; }
  192. /// <summary>
  193. /// 提取文件
  194. /// </summary>
  195. public DelegateCommand ExtractCommand { get; set; }
  196. /// <summary>
  197. /// 逆时针旋转
  198. /// </summary>
  199. public DelegateCommand LeftRotateCommand { get; set; }
  200. /// <summary>
  201. /// 顺时针旋转
  202. /// </summary>
  203. public DelegateCommand RightRotateCommand { get; set; }
  204. /// <summary>
  205. /// 删除
  206. /// </summary>
  207. public DelegateCommand DeleteCommand { get; set; }
  208. /// <summary>
  209. /// 倒序
  210. /// </summary>
  211. public DelegateCommand ReverseCommand { get; set; }
  212. /// <summary>
  213. /// 放大
  214. /// </summary>
  215. public DelegateCommand ZoomInCommand { get; set; }
  216. /// <summary>
  217. /// 缩小
  218. /// </summary>
  219. public DelegateCommand ZoomOutCommand { get; set; }
  220. #endregion
  221. public PageEditContentViewModel(IDialogService dialogService, IEventAggregator eventAggregator)
  222. {
  223. //变量初始化
  224. dialogs = dialogService;
  225. eventor = eventAggregator;
  226. unicode = App.mainWindowViewModel.SelectedItem.Unicode;
  227. PageEditItems = new ObservableCollection<PageEditItem>();
  228. PageRangeItems = new ObservableCollection<string>();
  229. //绑定命令
  230. SelectionChangedCommand = new DelegateCommand<object>(SelectionChangedEvent);
  231. PreviewKeyDown = new DelegateCommand<object>(PreviewKeyDownEvent);
  232. KeyDown = new DelegateCommand<object>(KeyDownEvent);
  233. SplitCommand = new DelegateCommand(SplitCommandEvent);
  234. InsertCommand = new DelegateCommand(InsertCommandEvent);
  235. ReplaceCommand = new DelegateCommand(ReplaceCommandEvent, CanReplaceCommandExcute).ObservesProperty(() => IsMutiSelected);
  236. ExtractCommand = new DelegateCommand(ExtractCommandEvent, CanFileCommandExcute).ObservesProperty(() => ListSelectedIndex);
  237. DeleteCommand = new DelegateCommand(DeleteCommandEvent, CanFileCommandExcute).ObservesProperty(() => ListSelectedIndex);
  238. LeftRotateCommand = new DelegateCommand(LeftRotateCommandEvent, CanFileCommandExcute).ObservesProperty(() => ListSelectedIndex);
  239. RightRotateCommand = new DelegateCommand(RightRotateCommandEvent, CanFileCommandExcute).ObservesProperty(() => ListSelectedIndex);
  240. ReverseCommand = new DelegateCommand(ReverseCommandEvent, CanFileCommandExcute).ObservesProperty(() => ListSelectedIndex);
  241. ZoomInCommand = new DelegateCommand(ZoomInCommandEvent, CanZoomIn).ObservesProperty(() => ZoomIndex);
  242. ZoomOutCommand = new DelegateCommand(ZoomOutCommandEvent, CanZoomOut).ObservesProperty(() => ZoomIndex);
  243. //订阅页面刷新事件
  244. eventAggregator.GetEvent<PageEditRefreshEvent>().Subscribe(OnPageEditRefreshEvent, e => e.Unicode == unicode);
  245. RefreshPageRangeItem();
  246. }
  247. #region 事件
  248. /// <summary>
  249. /// 替换功能的逻辑
  250. /// </summary>
  251. private async void ReplaceCommandEvent()
  252. {
  253. OpenFileDialog dialog = new OpenFileDialog();
  254. dialog.Multiselect = false;
  255. dialog.Filter = PDF_Office.Properties.Resources.OpenDialogFilter;
  256. if ((bool)dialog.ShowDialog())
  257. {
  258. IsLoading = Visibility.Visible;
  259. await Task.Delay(200);
  260. int pageCount = 0;
  261. int insertIndex = -1;
  262. CPDFDocument doc = CPDFDocument.InitWithFilePath(dialog.FileName);
  263. if (doc == null)
  264. {
  265. showTip = Visibility.Visible;
  266. return;
  267. }
  268. if (doc.IsLocked)
  269. {
  270. DialogParameters value = new DialogParameters();
  271. value.Add(ParameterNames.PDFDocument, doc);
  272. dialogs.ShowDialog(DialogNames.VerifyPassWordDialog, value, e =>
  273. {
  274. if (e.Result != ButtonResult.OK)
  275. {
  276. return;
  277. }
  278. });
  279. }
  280. pageCount = doc.PageCount;
  281. insertIndex = listSelecedIndex;
  282. //删除原有页面
  283. DeleteCommandEvent();
  284. //插入整个新文档
  285. //文档层插入
  286. await Task.Run(() =>
  287. {
  288. var result = PDFViewer.Document.ImportPagesAtIndex(doc, "1-" + pageCount, insertIndex);
  289. if (!result)
  290. {
  291. ShowTip = Visibility.Visible;
  292. return;
  293. }
  294. //插入成功后释放临时Document对象
  295. doc.Release();
  296. });
  297. //UI层插入
  298. for (int i = 0; i < pageCount; i++)
  299. {
  300. PageEditItem item = new PageEditItem();
  301. if (PDFViewer.Document.PageAtIndex(i).Rotation % 2 != 0)
  302. {
  303. ///标记为横向页面
  304. item.isVertical = false;
  305. }
  306. var pagesize = PDFViewer.Document.GetPageSize(i);
  307. item.PageSize = $"{pagesize.Width}mm*{pagesize.Height} mm";
  308. PageEditItems.Insert(insertIndex + i, item);
  309. }
  310. ReloadAfterOption(true, true, Tuple.Create(insertIndex, insertIndex + pageCount));
  311. //加一点延时才能显示选中效果
  312. await Task.Delay(400);
  313. for (int i = 0; i < pageCount; i++)
  314. {
  315. PageEditItems[insertIndex + i].Selected = true;
  316. }
  317. IsLoading = Visibility.Collapsed;
  318. }
  319. }
  320. /// <summary>
  321. /// 拆分功能的逻辑
  322. /// </summary>
  323. private void SplitCommandEvent()
  324. {
  325. }
  326. /// <summary>
  327. /// 提取功能的逻辑
  328. /// </summary>
  329. private void ExtractCommandEvent()
  330. {
  331. }
  332. /// <summary>
  333. /// 插入功能的逻辑
  334. /// </summary>
  335. private void InsertCommandEvent()
  336. {
  337. }
  338. /// <summary>
  339. /// 删除选中页面
  340. /// </summary>
  341. private void DeleteCommandEvent()
  342. {
  343. DoRemoveSelectedPages();
  344. ReloadAfterOption(true, true, null);
  345. }
  346. /// <summary>
  347. /// 左旋转页面的逻辑
  348. /// </summary>
  349. private void LeftRotateCommandEvent()
  350. {
  351. RotateSelectedPages(false);
  352. }
  353. /// <summary>
  354. /// 右旋转页面的逻辑
  355. /// </summary>
  356. private void RightRotateCommandEvent()
  357. {
  358. RotateSelectedPages();
  359. }
  360. /// <summary>
  361. /// 页面倒序的逻辑
  362. /// </summary>
  363. private void ReverseCommandEvent()
  364. {
  365. }
  366. /// <summary>
  367. /// 是否可以执行文件操作命令 除插入、拆分外
  368. /// </summary>
  369. /// <returns></returns>
  370. private bool CanFileCommandExcute()
  371. {
  372. if (ListSelectedIndex < 0)
  373. {
  374. return false;
  375. }
  376. else
  377. {
  378. return true;
  379. }
  380. }
  381. /// <summary>
  382. /// 校验是否可以替换
  383. /// </summary>
  384. /// <returns></returns>
  385. private bool CanReplaceCommandExcute()
  386. {
  387. return !IsMutiSelected;
  388. }
  389. /// <summary>
  390. /// 放大页面
  391. /// </summary>
  392. private void ZoomInCommandEvent()
  393. {
  394. for (int i = 0; i < PageEditItems.Count; i++)
  395. {
  396. PageEditItems[i].ItemSize = new Size(PageEditItems[i].ItemSize.Width * 2, PageEditItems[i].ItemSize.Height * 2);
  397. }
  398. ZoomIndex++;
  399. NotifyUIToRefresh();
  400. }
  401. /// <summary>
  402. /// 缩小页面
  403. /// </summary>
  404. private void ZoomOutCommandEvent()
  405. {
  406. for (int i = 0; i < PageEditItems.Count; i++)
  407. {
  408. PageEditItems[i].ItemSize = new Size(PageEditItems[i].ItemSize.Width / 2, PageEditItems[i].ItemSize.Height / 2);
  409. }
  410. ZoomIndex--;
  411. NotifyUIToRefresh();
  412. }
  413. private bool CanZoomIn()
  414. {
  415. if (ZoomIndex >= 1)
  416. {
  417. return false;
  418. }
  419. else
  420. {
  421. return true;
  422. }
  423. }
  424. private bool CanZoomOut()
  425. {
  426. if (ZoomIndex <= -1)
  427. {
  428. return false;
  429. }
  430. else
  431. {
  432. return true;
  433. }
  434. }
  435. /// <summary>
  436. /// 响应UI发送刷新图片的事件
  437. /// </summary>
  438. /// <param name="e"></param>
  439. private void OnPageEditRefreshEvent(PageEditRefreshEventArgs e)
  440. {
  441. //UI发送事件过来通知刷新图片时
  442. //调整逻辑,前后预加载5页
  443. RefreshItemImage(e.PageRange.Item1 - 2, e.PageRange.Item2 + 2);
  444. }
  445. /// <summary>
  446. /// 选项改变事件
  447. /// 虚拟化的时候不会触发选中事件
  448. /// </summary>
  449. /// <param name="e"></param>
  450. private void SelectionChangedEvent(object e)
  451. {
  452. var args = e as SelectionChangedEventArgs;
  453. var listbox = args.OriginalSource as ListBox;
  454. if (TbPageRangeVisibility == Visibility.Visible && args != null)
  455. {
  456. List<int> pagelist = new List<int>();
  457. for (int i = 0; i < listbox.SelectedItems.Count; i++)
  458. {
  459. pagelist.Add((listbox.SelectedItems[i] as PageEditItem).PageNumber);
  460. }
  461. //手动取消其他项的选中状态
  462. for (int j = 0; j < PageEditItems.Count; j++)
  463. {
  464. if (!pagelist.Contains(PageEditItems[j].PageNumber))
  465. {
  466. PageEditItems[j].Selected = false;
  467. }
  468. }
  469. ////根据选中的范围 适配全部页面范围、奇数页面范围等
  470. //if(pagelist.Count==PageEditItems.Count)
  471. //{
  472. // ComboxSelectIndex = 0;
  473. // return;
  474. //}
  475. string pageparm = CommonHelper.GetPageParmFromList(pagelist);
  476. TbPageRange = pageparm;
  477. }
  478. if (listbox.SelectedItem != null)
  479. {
  480. listbox.ScrollIntoView(listbox.SelectedItem);
  481. }
  482. //判断是否有选中多项
  483. if (listbox.SelectedItems.Count > 1)
  484. {
  485. IsMutiSelected = true;
  486. }
  487. else
  488. {
  489. IsMutiSelected = false;
  490. }
  491. }
  492. /// <summary>
  493. /// 限制文本框输入内容
  494. /// </summary>
  495. /// <param name="e"></param>
  496. private void PreviewKeyDownEvent(object e)
  497. {
  498. var args = e as KeyEventArgs;
  499. if (args == null)
  500. {
  501. return;
  502. }
  503. 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)))
  504. {
  505. args.Handled = true;
  506. }
  507. }
  508. /// <summary>
  509. /// 响应回车确认事件
  510. /// </summary>
  511. /// <param name="e"></param>
  512. private void KeyDownEvent(object e)
  513. {
  514. var args = e as KeyEventArgs;
  515. if (args == null)
  516. {
  517. return;
  518. }
  519. if (args.Key == Key.Enter)
  520. {
  521. List<int> TargetPageIndexs = new List<int>();
  522. var result = CommonHelper.GetPagesInRange(ref TargetPageIndexs, (args.OriginalSource as TextBox).Text, PDFViewer.Document.PageCount, new char[] { ',', ',' }, new char[] { '-' });
  523. if (!result)
  524. {
  525. MessageBox.Show("请输入有效范围");
  526. }
  527. //选中输入的页面范围
  528. for (int i = 0; i < PageEditItems.Count; i++)
  529. {
  530. if (TargetPageIndexs.Contains(PageEditItems[i].PageNumber - 1))
  531. {
  532. PageEditItems[i].Selected = true;
  533. }
  534. else
  535. {
  536. PageEditItems[i].Selected = false;
  537. }
  538. }
  539. }
  540. }
  541. #endregion
  542. #region 方法
  543. /// <summary>
  544. /// 通知UI刷新页面范围
  545. /// </summary>
  546. private void NotifyUIToRefresh()
  547. {
  548. //通知UI刷新页面范围
  549. eventor.GetEvent<PageEditNotifyEvent>().Publish(new PageEditNotifyEventArgs() { Unicode = unicode });
  550. }
  551. /// <summary>
  552. /// 删除选中项的方法 不带Reload操作
  553. /// 方便其他逻辑中调用
  554. /// </summary>
  555. private async void DoRemoveSelectedPages()
  556. {
  557. IsLoading = Visibility.Visible;
  558. await Task.Delay(3);
  559. List<int> indexList = new List<int>();
  560. for (int i = 0; i < PageEditItems.Count; i++)
  561. {
  562. if (PageEditItems[i].Selected)
  563. {
  564. indexList.Add(i);
  565. }
  566. }
  567. var result = PDFViewer.Document.RemovePages(indexList.ToArray());
  568. if (!result)
  569. {
  570. ShowTip = Visibility.Visible;
  571. return;
  572. }
  573. //文档层操作成功后再删除UI层
  574. for (int i = indexList.Count - 1; i >= 0; i--)
  575. {
  576. PageEditItems.RemoveAt(indexList[i]);
  577. }
  578. IsLoading = Visibility.Collapsed;
  579. }
  580. /// <summary>
  581. /// 进行文件操作后刷新PDFView
  582. /// 清除undo 栈
  583. /// 重加载Document
  584. /// 设置保存状态
  585. /// </summary>
  586. /// <param name="needRefreshPageNum">是否需要刷新页码</param>
  587. /// <param name="needClearUndoHistory">是否需要清空注释Undo栈</param>
  588. /// <param name="pageRange">需要刷新的页面范围图片</param>
  589. private void ReloadAfterOption(bool needRefreshPageNum = false, bool needClearUndoHistory = true, Tuple<int, int> pageRange = null)
  590. {
  591. if (needRefreshPageNum)
  592. {
  593. RefreshPageNum();
  594. }
  595. if (needClearUndoHistory)
  596. {
  597. PDFViewer.UndoManager.ClearHistory();
  598. }
  599. if (pageRange != null)
  600. {
  601. if (pageRange.Item2 - pageRange.Item1 > 30)
  602. {
  603. //范围较大时,通知UI获取更准确的刷新范围
  604. eventor.GetEvent<PageEditNotifyEvent>().Publish(new PageEditNotifyEventArgs() { Unicode = unicode });
  605. }
  606. else
  607. {
  608. RefreshItemImage(pageRange.Item1, pageRange.Item2);
  609. }
  610. }
  611. PDFViewer.UndoManager.CanSave = true;
  612. PDFViewer.ReloadDocument();
  613. }
  614. /// <summary>
  615. /// 旋转所有选中页面
  616. /// </summary>
  617. /// <param name="rightRotate"></param>
  618. private async void RotateSelectedPages(bool rightRotate = true)
  619. {
  620. IsLoading = Visibility.Visible;
  621. await Task.Delay(2);
  622. for (int i = 0; i < PageEditItems.Count; i++)
  623. {
  624. if (PageEditItems[i].Selected)
  625. {
  626. //逆时针旋转传 - 1 顺时针旋转传1
  627. PDFViewer.Document.RotatePage(i, rightRotate ? 1 : -1);
  628. PDFViewer.Document.ReleasePages(i);
  629. //重新拿图
  630. PageEditItems[i].isVertical = !PageEditItems[i].isVertical;
  631. PageEditItems[i].IsGetImage = false;
  632. }
  633. }
  634. ReloadAfterOption(false, true, Tuple.Create(0,PageEditItems.Count));
  635. IsLoading = Visibility.Collapsed;
  636. }
  637. /// <summary>
  638. /// 刷新页码
  639. /// </summary>
  640. private void RefreshPageNum()
  641. {
  642. for (int i = 0; i < PageEditItems.Count; i++)
  643. {
  644. PageEditItems[i].PageNumber = i + 1;
  645. }
  646. }
  647. /// <summary>
  648. /// 刷新页面范围下拉框
  649. /// </summary>
  650. private void RefreshPageRangeItem()
  651. {
  652. PageRangeItems.Clear();
  653. PageRangeItems.Add("所有页面");
  654. PageRangeItems.Add("奇数页");
  655. PageRangeItems.Add("偶数页");
  656. PageRangeItems.Add("横向页面");
  657. PageRangeItems.Add("纵向页面");
  658. PageRangeItems.Add("自定义");
  659. }
  660. /// <summary>
  661. /// 选中目标页面范围的页面
  662. /// </summary>
  663. /// <param name="index">页面范围选中项索引</param>
  664. private void SuitPageRange(int index)
  665. {
  666. switch (index)
  667. {
  668. case 0:
  669. for (int i = 0; i < PageEditItems.Count; i++)
  670. {
  671. PageEditItems[i].Selected = true;
  672. }
  673. break;
  674. case 1:
  675. //奇数页
  676. for (int i = 0; i < PageEditItems.Count; i++)
  677. {
  678. if (i % 2 == 0)
  679. {
  680. PageEditItems[i].Selected = true;
  681. }
  682. else
  683. {
  684. PageEditItems[i].Selected = false;
  685. }
  686. }
  687. break;
  688. case 2:
  689. //偶数页
  690. for (int i = 0; i < PageEditItems.Count; i++)
  691. {
  692. if (i % 2 == 0)
  693. {
  694. PageEditItems[i].Selected = false;
  695. }
  696. else
  697. {
  698. PageEditItems[i].Selected = true;
  699. }
  700. }
  701. break;
  702. case 3://横向页面
  703. for (int i = 0; i < PageEditItems.Count; i++)
  704. {
  705. if (PDFViewer.Document.PageAtIndex(i).Rotation % 2 == 0)
  706. {
  707. PageEditItems[i].Selected = false;
  708. }
  709. else
  710. {
  711. PageEditItems[i].Selected = true;
  712. }
  713. }
  714. break;
  715. case 4://纵向页面
  716. for (int i = 0; i < PageEditItems.Count; i++)
  717. {
  718. if (PDFViewer.Document.PageAtIndex(i).Rotation % 2 == 0)
  719. {
  720. PageEditItems[i].Selected = true;
  721. }
  722. else
  723. {
  724. PageEditItems[i].Selected = false;
  725. }
  726. }
  727. break;
  728. case 5://自定义
  729. //取消所有选中
  730. ListSelectedIndex = -1;
  731. TxtPageInputVisibility = Visibility.Visible;
  732. break;
  733. default:
  734. break;
  735. }
  736. }
  737. /// <summary>
  738. /// 是否显示页面尺寸
  739. /// </summary>
  740. /// <param name="show">是或否</param>
  741. private void ShowPageSize(bool show = true)
  742. {
  743. for (int i = 0; i < PageEditItems.Count; i++)
  744. {
  745. PageEditItems[i].ShowPageSize = show;
  746. }
  747. }
  748. /// <summary>
  749. /// 从PDFView获取所有Items集合
  750. /// </summary>
  751. private void GetSourceItems(bool isFirstLoad)
  752. {
  753. if (isFirstLoad)
  754. {
  755. PageEditItems.Clear();
  756. for (int i = 0; i < PDFViewer.Document.PageCount; i++)
  757. {
  758. PageEditItem item = new PageEditItem();
  759. item.PageNumber = i + 1;
  760. if (PDFViewer.Document.PageAtIndex(i).Rotation % 2 != 0)
  761. {
  762. ///标记为横向页面
  763. item.isVertical = false;
  764. }
  765. var pagesize = PDFViewer.Document.GetPageSize(i);
  766. item.PageSize = $"{pagesize.Width}mm*{pagesize.Height} mm";
  767. PageEditItems.Add(item);
  768. }
  769. }
  770. else
  771. {
  772. //后续进来仅刷新图片即可
  773. for (int i = 0; i < PageEditItems.Count; i++)
  774. {
  775. PageEditItems[i].IsGetImage = false;
  776. }
  777. }
  778. }
  779. /// <summary>
  780. /// 刷新书签列表
  781. /// </summary>
  782. public void RefreshBookMarkList()
  783. {
  784. if (PDFViewer != null)
  785. {
  786. var booklist = PDFViewer.Document.GetBookmarkList();
  787. if (booklist == null)
  788. {
  789. return;
  790. }
  791. //获取所有书签的Index集合
  792. List<int> marks = new List<int>();
  793. for (int i = 0; i < booklist.Count; i++)
  794. {
  795. marks.Add(booklist[i].PageIndex);
  796. }
  797. //不能只遍历marks集合,考虑书签集合元素删除的情况
  798. for (int k = 0; k < PageEditItems.Count; k++)
  799. {
  800. if (marks.Contains(k))
  801. PageEditItems[k].HaveBookMark = true;
  802. else
  803. PageEditItems[k].HaveBookMark = false;
  804. }
  805. }
  806. }
  807. /// <summary>
  808. /// 刷新指定范围的图片
  809. /// </summary>
  810. /// <param name="startIndex"></param>
  811. /// <param name="endIndex"></param>
  812. private async void RefreshItemImage(int startIndex, int endIndex)
  813. {
  814. for (int i = startIndex; i <= endIndex; i++)
  815. {
  816. if (i <= PDFViewer.Document.PageCount - 1 && i >= 0 && PageEditItems.Count > 0)
  817. {
  818. //宽高为样式中图片控件宽高
  819. if (PageEditItems[i].isVertical)
  820. {
  821. await PDFViewer.GetThumbnail(i, 208, 294);
  822. }
  823. else
  824. {
  825. //获取横图
  826. await PDFViewer.GetThumbnail(i, 294, 208);
  827. }
  828. }
  829. }
  830. }
  831. /// <summary>
  832. /// 从底层库获取对应页面的图片
  833. /// </summary>
  834. /// <param name="pageIndex"></param>
  835. /// <param name="thumb"></param>
  836. /// <param name="w"></param>
  837. /// <param name="h"></param>
  838. private void PDFViewer_OnThumbnailGenerated(int pageIndex, byte[] thumb, int w, int h)
  839. {
  840. try
  841. {
  842. if (PageEditItems.Count >= pageIndex + 1 && !PageEditItems[pageIndex].IsGetImage)
  843. {
  844. PixelFormat fmt = PixelFormats.Bgra32;
  845. BitmapSource bps = BitmapSource.Create(w, h, 96.0, 96.0, fmt, null, thumb, (w * fmt.BitsPerPixel + 7) / 8);
  846. PageEditItems[pageIndex].Image = bps;
  847. PageEditItems[pageIndex].IsGetImage = true;
  848. }
  849. }
  850. catch
  851. {
  852. }
  853. }
  854. #endregion
  855. #region Navigate
  856. public bool IsNavigationTarget(NavigationContext navigationContext)
  857. {
  858. return true;
  859. }
  860. public void OnNavigatedFrom(NavigationContext navigationContext)
  861. {
  862. }
  863. /// <summary>
  864. /// 从其他页面导航过来的时候会触发
  865. /// 考虑只有在页面编辑的时候会进行页面的删减,可以尝试逻辑优化:仅第一次进入页面编辑时重新刷新页面
  866. /// </summary>
  867. /// <param name="navigationContext"></param>
  868. public void OnNavigatedTo(NavigationContext navigationContext)
  869. {
  870. navigationContext.Parameters.TryGetValue<ViewContentViewModel>(ParameterNames.ViewContentViewModel, out viewContentViewModel);
  871. navigationContext.Parameters.TryGetValue<CPDFViewer>(ParameterNames.PDFViewer, out PDFViewer);
  872. if (PDFViewer != null)
  873. {
  874. if (isFirstLoad)
  875. {
  876. PDFViewer.OnThumbnailGenerated += PDFViewer_OnThumbnailGenerated;
  877. ZoomIndex = 0;
  878. }
  879. GetSourceItems(isFirstLoad);
  880. ListSelectedIndex = PDFViewer.CurrentIndex;
  881. RefreshBookMarkList();
  882. isFirstLoad = false;
  883. }
  884. }
  885. #endregion
  886. }
  887. }