PageEditContentViewModel.cs 44 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370
  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. dialogs.ShowDialog(DialogNames.SplitDialog, null, null);
  324. }
  325. /// <summary>
  326. /// 提取功能的逻辑
  327. /// </summary>
  328. private void ExtractCommandEvent()
  329. {
  330. dialogs.ShowDialog(DialogNames.ExtractDialog,null,e=> {
  331. if(e.Result==ButtonResult.OK&&e.Parameters!=null)
  332. {
  333. var model = e.Parameters.GetValue<ExtractModel>(ParameterNames.DataModel);
  334. DoExtractPages(model.IsEveryPageToFile,model.IsDeleteAfterExtract);
  335. }
  336. });
  337. }
  338. /// <summary>
  339. /// 插入功能的逻辑
  340. /// </summary>
  341. private async void InsertCommandEvent(object type)
  342. {
  343. if((string)type==null)
  344. {
  345. return;
  346. }
  347. //获取插入位置
  348. int insertIndex = 0;
  349. if(listSelecedIndex<0)
  350. {
  351. insertIndex = 0;
  352. }
  353. else
  354. {
  355. insertIndex = listSelecedIndex+1;
  356. if(isMutiSelected)
  357. {
  358. insertIndex = maxSelectedIndex+1;
  359. }
  360. }
  361. IsLoading = Visibility.Visible;
  362. await Task.Delay(3);
  363. if((string)type==ParameterNames.InsertType_Blank)
  364. {
  365. //插入空白页面
  366. bool result;
  367. if (insertIndex == 0)
  368. {
  369. result = PDFViewer.Document.InsertPage(insertIndex, PageEditItems[insertIndex].Size.Width, PageEditItems[insertIndex].Size.Height, null);
  370. }
  371. else
  372. {
  373. result = PDFViewer.Document.InsertPage(insertIndex, PageEditItems[insertIndex-1].Size.Width, PageEditItems[insertIndex-1].Size.Height, null);
  374. }
  375. if(!result)
  376. {
  377. IsLoading = Visibility.Collapsed;
  378. ShowTip = Visibility.Visible;
  379. return;
  380. }
  381. //UI层插入Item
  382. var item = GetNewPageEditItem(insertIndex);
  383. PageEditItems.Insert(insertIndex,item);
  384. ReloadAfterOption(true,true,Tuple.Create(insertIndex,insertIndex+1));
  385. await Task.Delay(10);
  386. ListSelectedIndex = insertIndex == 0 ? insertIndex : insertIndex;
  387. }
  388. else if((string)type == ParameterNames.InsertType_File)
  389. {
  390. OpenFileDialog dialog = new OpenFileDialog();
  391. dialog.Multiselect = false;
  392. dialog.Filter = PDF_Office.Properties.Resources.OpenDialogFilter;
  393. if ((bool)dialog.ShowDialog())
  394. {
  395. //插入文件
  396. var result = await InsertFromFile(insertIndex,dialog.FileName);
  397. if(!result)
  398. {
  399. IsLoading = Visibility.Collapsed;
  400. ShowTip = Visibility.Visible;
  401. return;
  402. }
  403. ReloadAfterOption(true,true,Tuple.Create(0,PDFViewer.Document.PageCount));
  404. }
  405. }
  406. else
  407. {
  408. //插入自定义页面
  409. dialogs.ShowDialog(DialogNames.InsertDialog, null, null);
  410. }
  411. IsLoading = Visibility.Collapsed;
  412. }
  413. /// <summary>
  414. /// 删除选中页面
  415. /// </summary>
  416. private async void DeleteCommandEvent()
  417. {
  418. IsLoading = Visibility.Visible;
  419. await Task.Delay(3);
  420. DoRemoveSelectedPages();
  421. ReloadAfterOption(true, true, Tuple.Create(0,PDFViewer.Document.PageCount));
  422. IsLoading = Visibility.Collapsed;
  423. }
  424. /// <summary>
  425. /// 左旋转页面的逻辑
  426. /// </summary>
  427. private void LeftRotateCommandEvent()
  428. {
  429. RotateSelectedPages(false);
  430. }
  431. /// <summary>
  432. /// 右旋转页面的逻辑
  433. /// </summary>
  434. private void RightRotateCommandEvent()
  435. {
  436. RotateSelectedPages();
  437. }
  438. /// <summary>
  439. /// 页面倒序的逻辑
  440. /// </summary>
  441. private async void ReverseCommandEvent()
  442. {
  443. IsLoading = Visibility.Visible;
  444. await Task.Delay(3);
  445. List<int> pages = new List<int>();
  446. for (int i = 0; i <PageEditItems.Count; i++)
  447. {
  448. if (PageEditItems[i].Selected)
  449. {
  450. pages.Add(i);
  451. }
  452. }
  453. if(pages.Count<=1)
  454. {
  455. ShowToast("请至少选择两个图片进行倒序操作。");
  456. return;
  457. }
  458. pages.Sort();
  459. for (int i = 0; i < pages.Count; i++)
  460. {
  461. int preindex = pages[i];
  462. int laterIndex = pages[pages.Count - i - 1];//尾部的索引
  463. if (laterIndex <= preindex)//交换完成
  464. {
  465. break;
  466. }
  467. var sourceitem = PageEditItems[preindex];
  468. var targetitem = PageEditItems[laterIndex];
  469. var result = PDFViewer.Document.ExchangePage(preindex, laterIndex);
  470. if(!result)
  471. {
  472. ShowTip = Visibility.Visible;
  473. IsLoading = Visibility.Collapsed;
  474. return;
  475. }
  476. PageEditItems.Remove(sourceitem);
  477. PageEditItems.Remove(targetitem);
  478. PageEditItems.Insert(preindex, targetitem);
  479. PageEditItems.Insert(laterIndex, sourceitem);
  480. }
  481. await Task.Delay(20);
  482. for(int i=0;i<pages.Count;i++)
  483. {
  484. PageEditItems[i].Selected = true;
  485. }
  486. ReloadAfterOption(true,true,null);
  487. IsLoading = Visibility.Collapsed;
  488. }
  489. /// <summary>
  490. /// 是否可以执行文件操作命令 除插入、拆分外
  491. /// </summary>
  492. /// <returns></returns>
  493. private bool CanFileCommandExcute()
  494. {
  495. if (ListSelectedIndex < 0)
  496. {
  497. return false;
  498. }
  499. else
  500. {
  501. return true;
  502. }
  503. }
  504. /// <summary>
  505. /// 校验是否可以替换
  506. /// </summary>
  507. /// <returns></returns>
  508. private bool CanReplaceCommandExcute()
  509. {
  510. return !IsMutiSelected;
  511. }
  512. /// <summary>
  513. /// 放大页面
  514. /// </summary>
  515. private void ZoomInCommandEvent()
  516. {
  517. ChangeItemSize(new Size(PageEditItems[0].ItemSize.Width *2, PageEditItems[0].ItemSize.Height *2));
  518. ZoomIndex++;
  519. NotifyUIToRefresh();
  520. }
  521. /// <summary>
  522. /// 缩小页面
  523. /// </summary>
  524. private void ZoomOutCommandEvent()
  525. {
  526. ChangeItemSize(new Size(PageEditItems[0].ItemSize.Width / 2, PageEditItems[0].ItemSize.Height / 2));
  527. ZoomIndex--;
  528. NotifyUIToRefresh();
  529. }
  530. /// <summary>
  531. ///
  532. /// </summary>
  533. /// <param name="newsize"></param>
  534. public void ChangeItemSize(Size newsize)
  535. {
  536. for (int i = 0; i < PageEditItems.Count; i++)
  537. {
  538. PageEditItems[i].ItemSize = newsize;
  539. }
  540. }
  541. private bool CanZoomIn()
  542. {
  543. if (ZoomIndex >= 1)
  544. {
  545. return false;
  546. }
  547. else
  548. {
  549. return true;
  550. }
  551. }
  552. private bool CanZoomOut()
  553. {
  554. if (ZoomIndex <= -1)
  555. {
  556. return false;
  557. }
  558. else
  559. {
  560. return true;
  561. }
  562. }
  563. /// <summary>
  564. /// 响应UI发送刷新图片的事件
  565. /// </summary>
  566. /// <param name="e"></param>
  567. private void OnPageEditRefreshEvent(PageEditRefreshEventArgs e)
  568. {
  569. //UI发送事件过来通知刷新图片时
  570. //调整逻辑,前后预加载5页
  571. RefreshItemImage(e.PageRange.Item1 - 2, e.PageRange.Item2 + 2);
  572. }
  573. /// <summary>
  574. /// 选项改变事件
  575. /// 虚拟化的时候不会触发选中事件
  576. /// </summary>
  577. /// <param name="e"></param>
  578. private void SelectionChangedEvent(object e)
  579. {
  580. //var args = e as SelectionChangedEventArgs;
  581. //var listbox = args.OriginalSource as ListBox;
  582. //if (TbPageRangeVisibility == Visibility.Visible && args != null)
  583. //{
  584. // List<int> pagelist = new List<int>();
  585. // for (int i = 0; i < listbox.SelectedItems.Count; i++)
  586. // {
  587. // if (!pagelist.Contains((listbox.SelectedItems[i] as PageEditItem).PageNumber))
  588. // {
  589. // pagelist.Add((listbox.SelectedItems[i] as PageEditItem).PageNumber);
  590. // }
  591. // }
  592. // ////手动取消其他项的选中状态
  593. // //for (int j = 0; j < PageEditItems.Count; j++)
  594. // //{
  595. // // if (!pagelist.Contains(PageEditItems[j].PageNumber))
  596. // // {
  597. // // PageEditItems[j].Selected = false;
  598. // // }
  599. // //}
  600. // ////根据选中的范围 适配全部页面范围、奇数页面范围等
  601. // //if(pagelist.Count==PageEditItems.Count)
  602. // //{
  603. // // ComboxSelectIndex = 0;
  604. // // return;
  605. // //}
  606. // string pageparm = CommonHelper.GetPageParmFromList(pagelist);
  607. // TbPageRange = pageparm;
  608. //}
  609. //if (listbox.SelectedItem != null)
  610. //{
  611. // listbox.ScrollIntoView(listbox.SelectedItem);
  612. //}
  613. ////判断是否有选中多项
  614. //if (listbox.SelectedItems.Count > 1)
  615. //{
  616. // IsMutiSelected = true;
  617. // maxSelectedIndex = listbox.Items.IndexOf(listbox.SelectedItems[listbox.SelectedItems.Count-1]);
  618. //}
  619. //else
  620. //{
  621. // IsMutiSelected = false;
  622. //}
  623. }
  624. /// <summary>
  625. /// 限制文本框输入内容
  626. /// </summary>
  627. /// <param name="e"></param>
  628. private void PreviewKeyDownEvent(object e)
  629. {
  630. var args = e as KeyEventArgs;
  631. if (args == null)
  632. {
  633. return;
  634. }
  635. 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)))
  636. {
  637. args.Handled = true;
  638. }
  639. }
  640. /// <summary>
  641. /// 响应回车确认事件
  642. /// </summary>
  643. /// <param name="e"></param>
  644. private void KeyDownEvent(object e)
  645. {
  646. var args = e as KeyEventArgs;
  647. if (args == null)
  648. {
  649. return;
  650. }
  651. if (args.Key == Key.Enter)
  652. {
  653. List<int> TargetPageIndexs = new List<int>();
  654. var result = CommonHelper.GetPagesInRange(ref TargetPageIndexs, (args.OriginalSource as TextBox).Text, PDFViewer.Document.PageCount, new char[] { ',', ',' }, new char[] { '-' });
  655. if (!result)
  656. {
  657. AlertsMessage alertsMessage = new AlertsMessage();
  658. alertsMessage.ShowDialog("","请输入有效范围","OK");
  659. return;
  660. }
  661. //选中输入的页面范围
  662. for (int i = 0; i < PageEditItems.Count; i++)
  663. {
  664. if (TargetPageIndexs.Contains(PageEditItems[i].PageNumber - 1))
  665. {
  666. PageEditItems[i].Selected = true;
  667. }
  668. else
  669. {
  670. PageEditItems[i].Selected = false;
  671. }
  672. }
  673. }
  674. }
  675. #endregion
  676. #region 方法
  677. /// <summary>
  678. /// 退出页面编辑面试,回到阅读页
  679. /// </summary>
  680. public void BackToPDFViewer(int PageIndex)
  681. {
  682. PDFViewer.GoToPage(PageIndex);
  683. viewContentViewModel.ExitToolMode();
  684. }
  685. /// <summary>
  686. /// 显示Toast提示
  687. /// </summary>
  688. private void ShowToast(string content)
  689. {
  690. if (!string.IsNullOrEmpty(content))
  691. {
  692. ToastText = content;
  693. }
  694. else
  695. {
  696. ToastText = "操作失败";
  697. }
  698. ShowTip = Visibility.Visible;
  699. }
  700. /// <summary>
  701. /// 通知UI刷新页面范围
  702. /// 或通过xaml来设置选中项
  703. /// </summary>vb nmjvcx
  704. private void NotifyUIToRefresh(List<int> pageRange=null)
  705. {
  706. if (pageRange == null || pageRange.Count <= 0)
  707. {
  708. //通知UI刷新页面范围
  709. eventor.GetEvent<PageEditNotifyEvent>().Publish(new PageEditNotifyEventArgs(unicode));
  710. }
  711. else
  712. {
  713. //通知UI刷新页面范围
  714. eventor.GetEvent<PageEditNotifyEvent>().Publish(new PageEditNotifyEventArgs(unicode,NotifyType.SelectItems,pageRange));
  715. }
  716. }
  717. /// <summary>
  718. /// 删除选中项的方法 不带Reload操作
  719. /// 方便其他逻辑中调用
  720. /// </summary>
  721. private void DoRemoveSelectedPages(List<int> pageList = null)
  722. {
  723. List<int> indexList = new List<int>();
  724. if (pageList == null || pageList.Count < 0)
  725. {
  726. for (int i = 0; i < PageEditItems.Count; i++)
  727. {
  728. if (PageEditItems[i].Selected)
  729. {
  730. indexList.Add(i);
  731. }
  732. }
  733. }
  734. else
  735. {
  736. indexList = pageList;
  737. }
  738. if(indexList.Count>0&& indexList.Count==PDFViewer.Document.PageCount)
  739. {
  740. AlertsMessage alertsMessage = new AlertsMessage();
  741. alertsMessage.ShowDialog("","不能删除所有页面","OK");
  742. return;
  743. }
  744. var result = PDFViewer.Document.RemovePages(indexList.ToArray());
  745. if (!result)
  746. {
  747. ShowTip = Visibility.Visible;
  748. return;
  749. }
  750. //文档层操作成功后再删除UI层
  751. for (int i = indexList.Count - 1; i >= 0; i--)
  752. {
  753. PageEditItems.RemoveAt(indexList[i]);
  754. }
  755. }
  756. /// <summary>
  757. /// 提取选中页面的方法
  758. /// </summary>
  759. /// <param name="isEveryPageToFile">是否每页生成一个文件</param>
  760. /// <param name="isDeleteAfterExtract">是否提取后删除页面</param>
  761. private async void DoExtractPages(bool isEveryPageToFile,bool isDeleteAfterExtract)
  762. {
  763. System.Windows.Forms.FolderBrowserDialog dialog = new System.Windows.Forms.FolderBrowserDialog();
  764. if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
  765. {
  766. if (string.IsNullOrEmpty(dialog.SelectedPath))
  767. {
  768. AlertsMessage alertsMessage = new AlertsMessage();
  769. alertsMessage.ShowDialog("","","OK");//补充提示文案
  770. return;
  771. }
  772. }
  773. else
  774. return;
  775. string selectedfile = "";
  776. IsLoading = Visibility.Visible;
  777. await Task.Delay(3);
  778. List<int> pagenums = new List<int>();
  779. for(int i=0;i<PageEditItems.Count;i++)
  780. {
  781. if(PageEditItems[i].Selected)
  782. {
  783. pagenums.Add(PageEditItems[i].PageNumber);
  784. }
  785. }
  786. if (isEveryPageToFile)
  787. {
  788. //每页生成的单独的文件
  789. for (int i = 0; i < pagenums.Count; i++)
  790. {
  791. string filename = PDFViewer.Document.FileName + " " + pagenums[i] + ".pdf";
  792. string path = System.IO.Path.Combine(dialog.SelectedPath, filename);
  793. path = CommonHelper.CreateFilePath(path);
  794. selectedfile = path;
  795. CPDFDocument savedoc = CPDFDocument.CreateDocument();
  796. bool result = savedoc.ImportPages(PDFViewer.Document, pagenums[i].ToString());
  797. if (!result)
  798. {
  799. savedoc.Release();
  800. continue;
  801. }
  802. result = savedoc.WriteToFilePath(path);
  803. if (!result)
  804. {
  805. savedoc.Release();
  806. continue;
  807. }
  808. savedoc.Release();//释放内存
  809. }
  810. }
  811. else//全部生成一个文件
  812. {
  813. string filename = PDFViewer.Document.FileName + " " + CommonHelper.GetPageParmFromList(pagenums) + ".pdf";
  814. string path = System.IO.Path.Combine(dialog.SelectedPath, filename);
  815. path = CommonHelper.CreateFilePath(path);
  816. selectedfile = path;
  817. CPDFDocument savedoc = CPDFDocument.CreateDocument();
  818. string range = String.Join(",", pagenums);
  819. bool result = savedoc.ImportPages(PDFViewer.Document, range);
  820. if (!result)
  821. {
  822. ShowTip = Visibility.Visible;
  823. IsLoading = Visibility.Collapsed;
  824. return;
  825. }
  826. result = savedoc.WriteToFilePath(path);
  827. if (!result)
  828. {
  829. ShowTip = Visibility.Visible;
  830. }
  831. savedoc.Release();//释放内存
  832. }
  833. if(isDeleteAfterExtract)
  834. {
  835. DoRemoveSelectedPages();
  836. ReloadAfterOption(true,true,Tuple.Create(0,PDFViewer.Document.PageCount));
  837. }
  838. CommonHelper.ShowFileBrowser(selectedfile);
  839. IsLoading = Visibility.Collapsed;
  840. }
  841. /// <summary>
  842. /// 将文件插入到指定位置
  843. /// </summary>
  844. /// <param name="insertIndex"></param>
  845. private async Task<bool> InsertFromFile(int insertIndex,string filePath)
  846. {
  847. CPDFDocument doc = CPDFDocument.InitWithFilePath(filePath);
  848. if (doc == null)
  849. {
  850. showTip = Visibility.Visible;
  851. return false;
  852. }
  853. if (doc.IsLocked)
  854. {
  855. DialogParameters value = new DialogParameters();
  856. value.Add(ParameterNames.PDFDocument, doc);
  857. bool result = true;
  858. dialogs.ShowDialog(DialogNames.VerifyPassWordDialog, value,e=>
  859. {
  860. if (e.Result != ButtonResult.OK)
  861. {
  862. result = false;
  863. }
  864. });
  865. if(!result)
  866. {
  867. return false;
  868. }
  869. }
  870. int pageCount = doc.PageCount;
  871. //插入整个新文档
  872. //文档层插入
  873. await Task.Run(() =>
  874. {
  875. var result = PDFViewer.Document.ImportPagesAtIndex(doc, "1-" + pageCount, insertIndex);
  876. if (!result)
  877. {
  878. ShowTip = Visibility.Visible;
  879. return false;
  880. }
  881. //插入成功后释放临时Document对象
  882. doc.Release();
  883. return true;
  884. });
  885. //UI层插入
  886. for (int i = 0; i < pageCount; i++)
  887. {
  888. var item = GetNewPageEditItem(i);
  889. PageEditItems.Insert(insertIndex + i, item);
  890. }
  891. //加一点延时才能显示选中效果
  892. await Task.Delay(400);
  893. for (int i = 0; i < pageCount; i++)
  894. {
  895. PageEditItems[insertIndex + i].Selected = true;
  896. }
  897. return true;
  898. }
  899. /// <summary>
  900. /// 根据索引创建新的Item
  901. /// </summary>
  902. /// <param name="index"></param>
  903. /// <returns></returns>
  904. private PageEditItem GetNewPageEditItem(int index)
  905. {
  906. PageEditItem item = new PageEditItem();
  907. if (PDFViewer.Document.PageAtIndex(index).Rotation % 2 != 0)
  908. {
  909. ///标记为横向页面
  910. item.isVertical = false;
  911. }
  912. item.PageNumber = index + 1;
  913. var pagesize = PDFViewer.Document.GetPageSize(index);
  914. item.Size = pagesize;
  915. item.PageSize = $"{pagesize.Width}mm*{pagesize.Height} mm";
  916. return item;
  917. }
  918. /// <summary>
  919. /// 进行文件操作后刷新PDFView
  920. /// 清除undo 栈
  921. /// 重加载Document
  922. /// 设置保存状态
  923. /// </summary>
  924. /// <param name="needRefreshPageNum">是否需要刷新页码</param>
  925. /// <param name="needClearUndoHistory">是否需要清空注释Undo栈</param>
  926. /// <param name="pageRange">需要刷新的页面范围图片</param>
  927. private void ReloadAfterOption(bool needRefreshPageNum = false, bool needClearUndoHistory = true, Tuple<int, int> pageRange = null)
  928. {
  929. if (needRefreshPageNum)
  930. {
  931. RefreshPageNum();
  932. }
  933. if (needClearUndoHistory)
  934. {
  935. PDFViewer.UndoManager.ClearHistory();
  936. }
  937. if (pageRange != null)
  938. {
  939. if (pageRange.Item2 - pageRange.Item1 > 30)
  940. {
  941. //范围较大时,通知UI获取更准确的刷新范围
  942. NotifyUIToRefresh();
  943. }
  944. else
  945. {
  946. RefreshItemImage(pageRange.Item1, pageRange.Item2);
  947. }
  948. }
  949. PDFViewer.UndoManager.CanSave = true;
  950. PDFViewer.ReloadDocument();
  951. }
  952. /// <summary>
  953. /// 旋转所有选中页面
  954. /// </summary>
  955. /// <param name="rightRotate"></param>
  956. private async void RotateSelectedPages(bool rightRotate = true)
  957. {
  958. IsLoading = Visibility.Visible;
  959. await Task.Delay(2);
  960. for (int i = 0; i < PageEditItems.Count; i++)
  961. {
  962. if (PageEditItems[i].Selected)
  963. {
  964. //逆时针旋转传 - 1 顺时针旋转传1
  965. PDFViewer.Document.RotatePage(i, rightRotate ? 1 : -1);
  966. PDFViewer.Document.ReleasePages(i);
  967. //重新拿图
  968. PageEditItems[i].isVertical = !PageEditItems[i].isVertical;
  969. PageEditItems[i].IsGetImage = false;
  970. }
  971. }
  972. ReloadAfterOption(false, true, Tuple.Create(0, PageEditItems.Count));
  973. IsLoading = Visibility.Collapsed;
  974. }
  975. /// <summary>
  976. /// 刷新页码
  977. /// </summary>
  978. private void RefreshPageNum()
  979. {
  980. for (int i = 0; i < PageEditItems.Count; i++)
  981. {
  982. PageEditItems[i].PageNumber = i + 1;
  983. }
  984. }
  985. /// <summary>
  986. /// 刷新页面范围下拉框
  987. /// </summary>
  988. private void RefreshPageRangeItem()
  989. {
  990. PageRangeItems.Clear();
  991. PageRangeItems.Add("所有页面");
  992. PageRangeItems.Add("奇数页");
  993. PageRangeItems.Add("偶数页");
  994. PageRangeItems.Add("横向页面");
  995. PageRangeItems.Add("纵向页面");
  996. PageRangeItems.Add("自定义");
  997. }
  998. /// <summary>
  999. /// 选中目标页面范围的页面
  1000. /// </summary>
  1001. /// <param name="index">页面范围选中项索引</param>
  1002. private void SuitPageRange(int index)
  1003. {
  1004. switch (index)
  1005. {
  1006. case 0:
  1007. for (int i = 0; i < PageEditItems.Count; i++)
  1008. {
  1009. PageEditItems[i].Selected = true;
  1010. }
  1011. break;
  1012. case 1:
  1013. //奇数页
  1014. for (int i = 0; i < PageEditItems.Count; i++)
  1015. {
  1016. if (i % 2 == 0)
  1017. {
  1018. PageEditItems[i].Selected = true;
  1019. }
  1020. else
  1021. {
  1022. PageEditItems[i].Selected = false;
  1023. }
  1024. }
  1025. break;
  1026. case 2:
  1027. //偶数页
  1028. for (int i = 0; i < PageEditItems.Count; i++)
  1029. {
  1030. if (i % 2 == 0)
  1031. {
  1032. PageEditItems[i].Selected = false;
  1033. }
  1034. else
  1035. {
  1036. PageEditItems[i].Selected = true;
  1037. }
  1038. }
  1039. break;
  1040. case 3://横向页面
  1041. for (int i = 0; i < PageEditItems.Count; i++)
  1042. {
  1043. if (PDFViewer.Document.PageAtIndex(i).Rotation % 2 == 0)
  1044. {
  1045. PageEditItems[i].Selected = false;
  1046. }
  1047. else
  1048. {
  1049. PageEditItems[i].Selected = true;
  1050. }
  1051. }
  1052. break;
  1053. case 4://纵向页面
  1054. for (int i = 0; i < PageEditItems.Count; i++)
  1055. {
  1056. if (PDFViewer.Document.PageAtIndex(i).Rotation % 2 == 0)
  1057. {
  1058. PageEditItems[i].Selected = true;
  1059. }
  1060. else
  1061. {
  1062. PageEditItems[i].Selected = false;
  1063. }
  1064. }
  1065. break;
  1066. case 5://自定义
  1067. //取消所有选中
  1068. ListSelectedIndex = -1;
  1069. TxtPageInputVisibility = Visibility.Visible;
  1070. break;
  1071. default:
  1072. break;
  1073. }
  1074. }
  1075. /// <summary>
  1076. /// 是否显示页面尺寸
  1077. /// </summary>
  1078. /// <param name="show">是或否</param>
  1079. private void ShowPageSize(bool show = true)
  1080. {
  1081. for (int i = 0; i < PageEditItems.Count; i++)
  1082. {
  1083. PageEditItems[i].ShowPageSize = show;
  1084. }
  1085. }
  1086. /// <summary>
  1087. /// 从PDFView获取所有Items集合
  1088. /// </summary>
  1089. private void GetSourceItems(bool isFirstLoad)
  1090. {
  1091. if (isFirstLoad||IsBOTAThumb==Visibility.Visible)
  1092. {
  1093. PageEditItems.Clear();
  1094. for (int i = 0; i < PDFViewer.Document.PageCount; i++)
  1095. {
  1096. var item = GetNewPageEditItem(i);
  1097. PageEditItems.Add(item);
  1098. }
  1099. }
  1100. else
  1101. {
  1102. //后续进来仅刷新图片即可
  1103. for (int i = 0; i < PageEditItems.Count; i++)
  1104. {
  1105. PageEditItems[i].IsGetImage = false;
  1106. }
  1107. }
  1108. }
  1109. /// <summary>
  1110. /// 刷新书签列表
  1111. /// </summary>
  1112. public void RefreshBookMarkList()
  1113. {
  1114. if (PDFViewer != null)
  1115. {
  1116. var booklist = PDFViewer.Document.GetBookmarkList();
  1117. if (booklist == null)
  1118. {
  1119. return;
  1120. }
  1121. //获取所有书签的Index集合
  1122. List<int> marks = new List<int>();
  1123. for (int i = 0; i < booklist.Count; i++)
  1124. {
  1125. marks.Add(booklist[i].PageIndex);
  1126. }
  1127. //不能只遍历marks集合,考虑书签集合元素删除的情况
  1128. for (int k = 0; k < PageEditItems.Count; k++)
  1129. {
  1130. if (marks.Contains(k))
  1131. PageEditItems[k].HaveBookMark = true;
  1132. else
  1133. PageEditItems[k].HaveBookMark = false;
  1134. }
  1135. }
  1136. }
  1137. /// <summary>
  1138. /// 刷新指定范围的图片
  1139. /// </summary>
  1140. /// <param name="startIndex"></param>
  1141. /// <param name="endIndex"></param>
  1142. private async void RefreshItemImage(int startIndex, int endIndex)
  1143. {
  1144. for (int i = startIndex; i <= endIndex; i++)
  1145. {
  1146. if (i <= PDFViewer.Document.PageCount - 1 && i >= 0 && PageEditItems.Count > 0)
  1147. {
  1148. //宽高为样式中图片控件宽高
  1149. if (PageEditItems[i].isVertical)
  1150. {
  1151. await PDFViewer.GetThumbnail(i, 208, 294);
  1152. }
  1153. else
  1154. {
  1155. //获取横图
  1156. await PDFViewer.GetThumbnail(i, 294, 208);
  1157. }
  1158. }
  1159. }
  1160. }
  1161. /// <summary>
  1162. /// 从底层库获取对应页面的图片
  1163. /// </summary>
  1164. /// <param name="pageIndex"></param>
  1165. /// <param name="thumb"></param>
  1166. /// <param name="w"></param>
  1167. /// <param name="h"></param>
  1168. private void PDFViewer_OnThumbnailGenerated(int pageIndex, byte[] thumb, int w, int h)
  1169. {
  1170. try
  1171. {
  1172. if (PageEditItems.Count >= pageIndex + 1)
  1173. {
  1174. PixelFormat fmt = PixelFormats.Bgra32;
  1175. BitmapSource bps = BitmapSource.Create(w, h, 96.0, 96.0, fmt, null, thumb, (w * fmt.BitsPerPixel + 7) / 8);
  1176. PageEditItems[pageIndex].Image = bps;
  1177. PageEditItems[pageIndex].IsGetImage = true;
  1178. }
  1179. }
  1180. catch
  1181. {
  1182. }
  1183. }
  1184. #endregion
  1185. #region Navigate
  1186. public bool IsNavigationTarget(NavigationContext navigationContext)
  1187. {
  1188. return true;
  1189. }
  1190. public void OnNavigatedFrom(NavigationContext navigationContext)
  1191. {
  1192. }
  1193. /// <summary>
  1194. /// 从其他页面导航过来的时候会触发
  1195. /// 考虑只有在页面编辑的时候会进行页面的删减,可以尝试逻辑优化:仅第一次进入页面编辑时重新刷新页面
  1196. /// </summary>
  1197. /// <param name="navigationContext"></param>
  1198. public void OnNavigatedTo(NavigationContext navigationContext)
  1199. {
  1200. navigationContext.Parameters.TryGetValue<ViewContentViewModel>(ParameterNames.ViewContentViewModel, out viewContentViewModel);
  1201. navigationContext.Parameters.TryGetValue<CPDFViewer>(ParameterNames.PDFViewer, out PDFViewer);
  1202. bool isBOTA = false;
  1203. navigationContext.Parameters.TryGetValue<bool>(ParameterNames.BOTAThumb, out isBOTA);
  1204. if (PDFViewer != null)
  1205. {
  1206. if (isFirstLoad)
  1207. {
  1208. PDFViewer.OnThumbnailGenerated += PDFViewer_OnThumbnailGenerated;
  1209. PDFViewer.InfoChanged += PDFViewer_InfoChanged;
  1210. ZoomIndex = 0;
  1211. }
  1212. //BOTA缩略图时,显示不同的菜单栏
  1213. if(isBOTA)
  1214. {
  1215. IsBOTAThumb = Visibility.Visible;
  1216. }
  1217. GetSourceItems(isFirstLoad);
  1218. ListSelectedIndex = PDFViewer.CurrentIndex;
  1219. RefreshBookMarkList();
  1220. isFirstLoad = false;
  1221. }
  1222. }
  1223. private void PDFViewer_InfoChanged(object sender, KeyValuePair<string, object> e)
  1224. {
  1225. if(e.Key== "PageNum")
  1226. {
  1227. NotifyUIToRefresh(new List<int> { (int)e.Value});
  1228. }
  1229. }
  1230. #endregion
  1231. }
  1232. }