using Prism.Mvvm; using Prism.Regions; using Prism.Services.Dialogs; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Media; using ComPDFKitViewer.PdfViewer; using PDF_Office.Model; using System.Collections.ObjectModel; using PDF_Office.Model.PageEdit; using Prism.Commands; using System.Windows; using System.Windows.Media.Imaging; using System.Windows.Controls.Primitives; using System.Diagnostics; using System.Windows.Controls; using System.Windows.Threading; using Prism.Events; using PDF_Office.EventAggregators; using System.Windows.Input; using PDF_Office.Helper; using Microsoft.Win32; using ComPDFKit.PDFDocument; namespace PDF_Office.ViewModels.PageEdit { public class PageEditContentViewModel : BindableBase, INavigationAware { private CPDFViewer PDFViewer; private ViewContentViewModel viewContentViewModel; private IDialogService dialogs; private IEventAggregator eventor; private string unicode = null; /// /// 项数据集合 /// public ObservableCollection PageEditItems { get; set; } /// /// 页面范围的项集合 /// public ObservableCollection PageRangeItems { get; set; } #region 属性 /// /// 是否是第一次加载 /// private bool isFirstLoad = true; private Visibility showTip = Visibility.Collapsed; /// /// 是否显示渐隐提示 /// public Visibility ShowTip { get { return showTip; } set { SetProperty(ref showTip, value); } } private Visibility isLoading = Visibility.Collapsed; /// /// 是否正在处理中 /// public Visibility IsLoading { get { return isLoading; } set { SetProperty(ref isLoading, value); } } private int listSelecedIndex; /// /// 缩略图选中项的索引 /// public int ListSelectedIndex { get { return listSelecedIndex; } set { SetProperty(ref listSelecedIndex, value); //显示页面范围选择控件 TbPageRangeVisibility = Visibility.Visible; TbPageRange = (ListSelectedIndex + 1).ToString(); TxtPageInputVisibility = Visibility.Collapsed; } } private bool isMutiSelected; /// /// 是否有多选 用于判断倒序和替换功能 /// public bool IsMutiSelected { get { return isMutiSelected; } set { SetProperty(ref isMutiSelected, value); } } private int comboxSelectIndex; /// /// 下拉框选项集合 /// public int ComboxSelectIndex { get { return comboxSelectIndex; } set { SetProperty(ref comboxSelectIndex, value); //选中指定的页面范围 SuitPageRange(comboxSelectIndex); //隐藏tb页面范围显示控件 TbPageRangeVisibility = Visibility.Collapsed; } } private Visibility tbPageRangeVisibility = Visibility.Visible; /// /// 页面范围的文本显示 /// public Visibility TbPageRangeVisibility { get { return tbPageRangeVisibility; } set { SetProperty(ref tbPageRangeVisibility, value); if (value == Visibility.Visible) { comboxSelectIndex = -1; } } } private string tbPageRange; /// /// 页面范围显示的内容 /// public string TbPageRange { get { return tbPageRange; } set { SetProperty(ref tbPageRange, value); } } private Visibility txtPageInputVisibility = Visibility.Collapsed; /// /// 页面自定义输入框的显示 /// public Visibility TxtPageInputVisibility { get { return txtPageInputVisibility; } set { SetProperty(ref txtPageInputVisibility, value); } } /// /// 页面缩放状态,-1 为最小值,1为最大值 /// private int zoomIndex = 0; public int ZoomIndex { get { return zoomIndex; } set { SetProperty(ref zoomIndex, value); } } #endregion #region 命令 public DelegateCommand SelectionChangedCommand { get; set; } /// /// 拦截键盘输入的事件 /// public DelegateCommand PreviewKeyDown { get; set; } /// /// 响应键盘回车事件 /// public DelegateCommand KeyDown { get; set; } /// /// 替换文件 /// public DelegateCommand ReplaceCommand { get; set; } /// /// 插入文件命令 /// public DelegateCommand InsertCommand { get; set; } /// /// 拆分文件 /// public DelegateCommand SplitCommand { get; set; } /// /// 提取文件 /// public DelegateCommand ExtractCommand { get; set; } /// /// 逆时针旋转 /// public DelegateCommand LeftRotateCommand { get; set; } /// /// 顺时针旋转 /// public DelegateCommand RightRotateCommand { get; set; } /// /// 删除 /// public DelegateCommand DeleteCommand { get; set; } /// /// 倒序 /// public DelegateCommand ReverseCommand { get; set; } /// /// 放大 /// public DelegateCommand ZoomInCommand { get; set; } /// /// 缩小 /// public DelegateCommand ZoomOutCommand { get; set; } #endregion public PageEditContentViewModel(IDialogService dialogService, IEventAggregator eventAggregator) { //变量初始化 dialogs = dialogService; eventor = eventAggregator; unicode = App.mainWindowViewModel.SelectedItem.Unicode; PageEditItems = new ObservableCollection(); PageRangeItems = new ObservableCollection(); //绑定命令 SelectionChangedCommand = new DelegateCommand(SelectionChangedEvent); PreviewKeyDown = new DelegateCommand(PreviewKeyDownEvent); KeyDown = new DelegateCommand(KeyDownEvent); SplitCommand = new DelegateCommand(SplitCommandEvent); InsertCommand = new DelegateCommand(InsertCommandEvent); ReplaceCommand = new DelegateCommand(ReplaceCommandEvent, CanReplaceCommandExcute).ObservesProperty(() => IsMutiSelected); ExtractCommand = new DelegateCommand(ExtractCommandEvent, CanFileCommandExcute).ObservesProperty(() => ListSelectedIndex); DeleteCommand = new DelegateCommand(DeleteCommandEvent, CanFileCommandExcute).ObservesProperty(() => ListSelectedIndex); LeftRotateCommand = new DelegateCommand(LeftRotateCommandEvent, CanFileCommandExcute).ObservesProperty(() => ListSelectedIndex); RightRotateCommand = new DelegateCommand(RightRotateCommandEvent, CanFileCommandExcute).ObservesProperty(() => ListSelectedIndex); ReverseCommand = new DelegateCommand(ReverseCommandEvent, CanFileCommandExcute).ObservesProperty(() => ListSelectedIndex); ZoomInCommand = new DelegateCommand(ZoomInCommandEvent, CanZoomIn).ObservesProperty(() => ZoomIndex); ZoomOutCommand = new DelegateCommand(ZoomOutCommandEvent, CanZoomOut).ObservesProperty(() => ZoomIndex); //订阅页面刷新事件 eventAggregator.GetEvent().Subscribe(OnPageEditRefreshEvent, e => e.Unicode == unicode); RefreshPageRangeItem(); } #region 事件 /// /// 替换功能的逻辑 /// private async void ReplaceCommandEvent() { OpenFileDialog dialog = new OpenFileDialog(); dialog.Multiselect = false; dialog.Filter = PDF_Office.Properties.Resources.OpenDialogFilter; if ((bool)dialog.ShowDialog()) { IsLoading = Visibility.Visible; await Task.Delay(200); int pageCount = 0; int insertIndex = -1; CPDFDocument doc = CPDFDocument.InitWithFilePath(dialog.FileName); if (doc == null) { showTip = Visibility.Visible; return; } if (doc.IsLocked) { DialogParameters value = new DialogParameters(); value.Add(ParameterNames.PDFDocument, doc); dialogs.ShowDialog(DialogNames.VerifyPassWordDialog, value, e => { if (e.Result != ButtonResult.OK) { return; } }); } pageCount = doc.PageCount; insertIndex = listSelecedIndex; //删除原有页面 DeleteCommandEvent(); //插入整个新文档 //文档层插入 await Task.Run(() => { var result = PDFViewer.Document.ImportPagesAtIndex(doc, "1-" + pageCount, insertIndex); if (!result) { ShowTip = Visibility.Visible; return; } //插入成功后释放临时Document对象 doc.Release(); }); //UI层插入 for (int i = 0; i < pageCount; i++) { PageEditItem item = new PageEditItem(); if (PDFViewer.Document.PageAtIndex(i).Rotation % 2 != 0) { ///标记为横向页面 item.isVertical = false; } var pagesize = PDFViewer.Document.GetPageSize(i); item.PageSize = $"{pagesize.Width}mm*{pagesize.Height} mm"; PageEditItems.Insert(insertIndex + i, item); } ReloadAfterOption(true, true, Tuple.Create(insertIndex, insertIndex + pageCount)); //加一点延时才能显示选中效果 await Task.Delay(400); for (int i = 0; i < pageCount; i++) { PageEditItems[insertIndex + i].Selected = true; } IsLoading = Visibility.Collapsed; } } /// /// 拆分功能的逻辑 /// private void SplitCommandEvent() { } /// /// 提取功能的逻辑 /// private void ExtractCommandEvent() { } /// /// 插入功能的逻辑 /// private void InsertCommandEvent() { } /// /// 删除选中页面 /// private void DeleteCommandEvent() { DoRemoveSelectedPages(); ReloadAfterOption(true, true, null); } /// /// 左旋转页面的逻辑 /// private void LeftRotateCommandEvent() { RotateSelectedPages(false); } /// /// 右旋转页面的逻辑 /// private void RightRotateCommandEvent() { RotateSelectedPages(); } /// /// 页面倒序的逻辑 /// private void ReverseCommandEvent() { } /// /// 是否可以执行文件操作命令 除插入、拆分外 /// /// private bool CanFileCommandExcute() { if (ListSelectedIndex < 0) { return false; } else { return true; } } /// /// 校验是否可以替换 /// /// private bool CanReplaceCommandExcute() { return !IsMutiSelected; } /// /// 放大页面 /// private void ZoomInCommandEvent() { for (int i = 0; i < PageEditItems.Count; i++) { PageEditItems[i].ItemSize = new Size(PageEditItems[i].ItemSize.Width * 2, PageEditItems[i].ItemSize.Height * 2); } ZoomIndex++; NotifyUIToRefresh(); } /// /// 缩小页面 /// private void ZoomOutCommandEvent() { for (int i = 0; i < PageEditItems.Count; i++) { PageEditItems[i].ItemSize = new Size(PageEditItems[i].ItemSize.Width / 2, PageEditItems[i].ItemSize.Height / 2); } ZoomIndex--; NotifyUIToRefresh(); } private bool CanZoomIn() { if (ZoomIndex >= 1) { return false; } else { return true; } } private bool CanZoomOut() { if (ZoomIndex <= -1) { return false; } else { return true; } } /// /// 响应UI发送刷新图片的事件 /// /// private void OnPageEditRefreshEvent(PageEditRefreshEventArgs e) { //UI发送事件过来通知刷新图片时 //调整逻辑,前后预加载5页 RefreshItemImage(e.PageRange.Item1 - 2, e.PageRange.Item2 + 2); } /// /// 选项改变事件 /// 虚拟化的时候不会触发选中事件 /// /// private void SelectionChangedEvent(object e) { var args = e as SelectionChangedEventArgs; var listbox = args.OriginalSource as ListBox; if (TbPageRangeVisibility == Visibility.Visible && args != null) { List pagelist = new List(); for (int i = 0; i < listbox.SelectedItems.Count; i++) { pagelist.Add((listbox.SelectedItems[i] as PageEditItem).PageNumber); } //手动取消其他项的选中状态 for (int j = 0; j < PageEditItems.Count; j++) { if (!pagelist.Contains(PageEditItems[j].PageNumber)) { PageEditItems[j].Selected = false; } } ////根据选中的范围 适配全部页面范围、奇数页面范围等 //if(pagelist.Count==PageEditItems.Count) //{ // ComboxSelectIndex = 0; // return; //} string pageparm = CommonHelper.GetPageParmFromList(pagelist); TbPageRange = pageparm; } if (listbox.SelectedItem != null) { listbox.ScrollIntoView(listbox.SelectedItem); } //判断是否有选中多项 if (listbox.SelectedItems.Count > 1) { IsMutiSelected = true; } else { IsMutiSelected = false; } } /// /// 限制文本框输入内容 /// /// private void PreviewKeyDownEvent(object e) { var args = e as KeyEventArgs; if (args == null) { return; } 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))) { args.Handled = true; } } /// /// 响应回车确认事件 /// /// private void KeyDownEvent(object e) { var args = e as KeyEventArgs; if (args == null) { return; } if (args.Key == Key.Enter) { List TargetPageIndexs = new List(); var result = CommonHelper.GetPagesInRange(ref TargetPageIndexs, (args.OriginalSource as TextBox).Text, PDFViewer.Document.PageCount, new char[] { ',', ',' }, new char[] { '-' }); if (!result) { MessageBox.Show("请输入有效范围"); } //选中输入的页面范围 for (int i = 0; i < PageEditItems.Count; i++) { if (TargetPageIndexs.Contains(PageEditItems[i].PageNumber - 1)) { PageEditItems[i].Selected = true; } else { PageEditItems[i].Selected = false; } } } } #endregion #region 方法 /// /// 通知UI刷新页面范围 /// private void NotifyUIToRefresh() { //通知UI刷新页面范围 eventor.GetEvent().Publish(new PageEditNotifyEventArgs() { Unicode = unicode }); } /// /// 删除选中项的方法 不带Reload操作 /// 方便其他逻辑中调用 /// private async void DoRemoveSelectedPages() { IsLoading = Visibility.Visible; await Task.Delay(3); List indexList = new List(); for (int i = 0; i < PageEditItems.Count; i++) { if (PageEditItems[i].Selected) { indexList.Add(i); } } var result = PDFViewer.Document.RemovePages(indexList.ToArray()); if (!result) { ShowTip = Visibility.Visible; return; } //文档层操作成功后再删除UI层 for (int i = indexList.Count - 1; i >= 0; i--) { PageEditItems.RemoveAt(indexList[i]); } IsLoading = Visibility.Collapsed; } /// /// 进行文件操作后刷新PDFView /// 清除undo 栈 /// 重加载Document /// 设置保存状态 /// /// 是否需要刷新页码 /// 是否需要清空注释Undo栈 /// 需要刷新的页面范围图片 private void ReloadAfterOption(bool needRefreshPageNum = false, bool needClearUndoHistory = true, Tuple pageRange = null) { if (needRefreshPageNum) { RefreshPageNum(); } if (needClearUndoHistory) { PDFViewer.UndoManager.ClearHistory(); } if (pageRange != null) { if (pageRange.Item2 - pageRange.Item1 > 30) { //范围较大时,通知UI获取更准确的刷新范围 eventor.GetEvent().Publish(new PageEditNotifyEventArgs() { Unicode = unicode }); } else { RefreshItemImage(pageRange.Item1, pageRange.Item2); } } PDFViewer.UndoManager.CanSave = true; PDFViewer.ReloadDocument(); } /// /// 旋转所有选中页面 /// /// private async void RotateSelectedPages(bool rightRotate = true) { IsLoading = Visibility.Visible; await Task.Delay(2); for (int i = 0; i < PageEditItems.Count; i++) { if (PageEditItems[i].Selected) { //逆时针旋转传 - 1 顺时针旋转传1 PDFViewer.Document.RotatePage(i, rightRotate ? 1 : -1); PDFViewer.Document.ReleasePages(i); //重新拿图 PageEditItems[i].isVertical = !PageEditItems[i].isVertical; PageEditItems[i].IsGetImage = false; } } ReloadAfterOption(false, true, Tuple.Create(0,PageEditItems.Count)); IsLoading = Visibility.Collapsed; } /// /// 刷新页码 /// private void RefreshPageNum() { for (int i = 0; i < PageEditItems.Count; i++) { PageEditItems[i].PageNumber = i + 1; } } /// /// 刷新页面范围下拉框 /// private void RefreshPageRangeItem() { PageRangeItems.Clear(); PageRangeItems.Add("所有页面"); PageRangeItems.Add("奇数页"); PageRangeItems.Add("偶数页"); PageRangeItems.Add("横向页面"); PageRangeItems.Add("纵向页面"); PageRangeItems.Add("自定义"); } /// /// 选中目标页面范围的页面 /// /// 页面范围选中项索引 private void SuitPageRange(int index) { switch (index) { case 0: for (int i = 0; i < PageEditItems.Count; i++) { PageEditItems[i].Selected = true; } break; case 1: //奇数页 for (int i = 0; i < PageEditItems.Count; i++) { if (i % 2 == 0) { PageEditItems[i].Selected = true; } else { PageEditItems[i].Selected = false; } } break; case 2: //偶数页 for (int i = 0; i < PageEditItems.Count; i++) { if (i % 2 == 0) { PageEditItems[i].Selected = false; } else { PageEditItems[i].Selected = true; } } break; case 3://横向页面 for (int i = 0; i < PageEditItems.Count; i++) { if (PDFViewer.Document.PageAtIndex(i).Rotation % 2 == 0) { PageEditItems[i].Selected = false; } else { PageEditItems[i].Selected = true; } } break; case 4://纵向页面 for (int i = 0; i < PageEditItems.Count; i++) { if (PDFViewer.Document.PageAtIndex(i).Rotation % 2 == 0) { PageEditItems[i].Selected = true; } else { PageEditItems[i].Selected = false; } } break; case 5://自定义 //取消所有选中 ListSelectedIndex = -1; TxtPageInputVisibility = Visibility.Visible; break; default: break; } } /// /// 是否显示页面尺寸 /// /// 是或否 private void ShowPageSize(bool show = true) { for (int i = 0; i < PageEditItems.Count; i++) { PageEditItems[i].ShowPageSize = show; } } /// /// 从PDFView获取所有Items集合 /// private void GetSourceItems(bool isFirstLoad) { if (isFirstLoad) { PageEditItems.Clear(); for (int i = 0; i < PDFViewer.Document.PageCount; i++) { PageEditItem item = new PageEditItem(); item.PageNumber = i + 1; if (PDFViewer.Document.PageAtIndex(i).Rotation % 2 != 0) { ///标记为横向页面 item.isVertical = false; } var pagesize = PDFViewer.Document.GetPageSize(i); item.PageSize = $"{pagesize.Width}mm*{pagesize.Height} mm"; PageEditItems.Add(item); } } else { //后续进来仅刷新图片即可 for (int i = 0; i < PageEditItems.Count; i++) { PageEditItems[i].IsGetImage = false; } } } /// /// 刷新书签列表 /// public void RefreshBookMarkList() { if (PDFViewer != null) { var booklist = PDFViewer.Document.GetBookmarkList(); if (booklist == null) { return; } //获取所有书签的Index集合 List marks = new List(); for (int i = 0; i < booklist.Count; i++) { marks.Add(booklist[i].PageIndex); } //不能只遍历marks集合,考虑书签集合元素删除的情况 for (int k = 0; k < PageEditItems.Count; k++) { if (marks.Contains(k)) PageEditItems[k].HaveBookMark = true; else PageEditItems[k].HaveBookMark = false; } } } /// /// 刷新指定范围的图片 /// /// /// private async void RefreshItemImage(int startIndex, int endIndex) { for (int i = startIndex; i <= endIndex; i++) { if (i <= PDFViewer.Document.PageCount - 1 && i >= 0 && PageEditItems.Count > 0) { //宽高为样式中图片控件宽高 if (PageEditItems[i].isVertical) { await PDFViewer.GetThumbnail(i, 208, 294); } else { //获取横图 await PDFViewer.GetThumbnail(i, 294, 208); } } } } /// /// 从底层库获取对应页面的图片 /// /// /// /// /// private void PDFViewer_OnThumbnailGenerated(int pageIndex, byte[] thumb, int w, int h) { try { if (PageEditItems.Count >= pageIndex + 1 && !PageEditItems[pageIndex].IsGetImage) { PixelFormat fmt = PixelFormats.Bgra32; BitmapSource bps = BitmapSource.Create(w, h, 96.0, 96.0, fmt, null, thumb, (w * fmt.BitsPerPixel + 7) / 8); PageEditItems[pageIndex].Image = bps; PageEditItems[pageIndex].IsGetImage = true; } } catch { } } #endregion #region Navigate public bool IsNavigationTarget(NavigationContext navigationContext) { return true; } public void OnNavigatedFrom(NavigationContext navigationContext) { } /// /// 从其他页面导航过来的时候会触发 /// 考虑只有在页面编辑的时候会进行页面的删减,可以尝试逻辑优化:仅第一次进入页面编辑时重新刷新页面 /// /// public void OnNavigatedTo(NavigationContext navigationContext) { navigationContext.Parameters.TryGetValue(ParameterNames.ViewContentViewModel, out viewContentViewModel); navigationContext.Parameters.TryGetValue(ParameterNames.PDFViewer, out PDFViewer); if (PDFViewer != null) { if (isFirstLoad) { PDFViewer.OnThumbnailGenerated += PDFViewer_OnThumbnailGenerated; ZoomIndex = 0; } GetSourceItems(isFirstLoad); ListSelectedIndex = PDFViewer.CurrentIndex; RefreshBookMarkList(); isFirstLoad = false; } } #endregion } }