|
@@ -0,0 +1,355 @@
|
|
|
+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 PDF_Office.Tools;
|
|
|
+using System.Windows.Threading;
|
|
|
+
|
|
|
+namespace PDF_Office.ViewModels.PageEdit
|
|
|
+{
|
|
|
+ public class PageEditContentViewModel : BindableBase, INavigationAware
|
|
|
+ {
|
|
|
+
|
|
|
+ private CPDFViewer PDFViewer;
|
|
|
+
|
|
|
+ private ViewContentViewModel viewContentViewModel;
|
|
|
+
|
|
|
+ private IDialogService dialogs;
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 是否正在初始化所有列表项,正在初始化时,不刷新图片
|
|
|
+ /// </summary>
|
|
|
+ private bool isInitaling = false;
|
|
|
+
|
|
|
+ private ScrollEventType scrollType = ScrollEventType.EndScroll;
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 辅助判断滚轮是否暂停滚动的计时器(暂时没有更好的方法来判断滚轮是否停止滚动)
|
|
|
+ /// 只要滚动就重新计时、通过计时开始0.3秒后没有刷新计时来粗略判断用户是否有暂停滚动
|
|
|
+ /// </summary>
|
|
|
+ private DispatcherTimer timer = new DispatcherTimer();
|
|
|
+
|
|
|
+ #region 属性
|
|
|
+ private Visibility isvisible;
|
|
|
+
|
|
|
+ public Visibility IsVisible
|
|
|
+ {
|
|
|
+ get { return isvisible; }
|
|
|
+ set
|
|
|
+ {
|
|
|
+ SetProperty(ref isvisible, value);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ #region 命令
|
|
|
+ /// <summary>
|
|
|
+ /// 是否显示 事件
|
|
|
+ /// </summary>
|
|
|
+ public DelegateCommand<object> IsVisibleChangedCommmand { get; set; }
|
|
|
+
|
|
|
+ public DelegateCommand<object> ScollChangedComamnd { get; set; }
|
|
|
+
|
|
|
+ public DelegateCommand<object> ScrollCommand { get; set; }
|
|
|
+
|
|
|
+ public DelegateCommand LoadCommand { get; set; }
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 项数据集合
|
|
|
+ /// </summary>
|
|
|
+ public ObservableCollection<PageEditItem> PageEditItems { get; set; }
|
|
|
+
|
|
|
+ public PageEditContentViewModel(IDialogService dialogService)
|
|
|
+ {
|
|
|
+ dialogs = dialogService;
|
|
|
+ PageEditItems = new ObservableCollection<PageEditItem>();
|
|
|
+ timer.Interval = TimeSpan.FromSeconds(0.2);
|
|
|
+ timer.Tick += Timer_Tick;
|
|
|
+
|
|
|
+
|
|
|
+ IsVisibleChangedCommmand = new DelegateCommand<object>(IsVisibleChangedEvent);
|
|
|
+ ScollChangedComamnd = new DelegateCommand<object>(ScrollChanged);
|
|
|
+ ScrollCommand = new DelegateCommand<object>(ScrollEvent);
|
|
|
+ LoadCommand = new DelegateCommand(ControlLoad);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ #region 事件
|
|
|
+ /// <summary>
|
|
|
+ /// 判断鼠标滚轮是否停止滚动的事件
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="sender"></param>
|
|
|
+ /// <param name="e"></param>
|
|
|
+ private void Timer_Tick(object sender, EventArgs e)
|
|
|
+ {
|
|
|
+ if (PDFViewer != null && PDFViewer.Document != null)
|
|
|
+ {
|
|
|
+ timer.Stop();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 鼠标滚轮滚动时触发的事件
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="e"></param>
|
|
|
+ private void ScrollChanged(object e)
|
|
|
+ {
|
|
|
+ var args = (ScrollChangedEventArgs)e;
|
|
|
+ var scrollviewer = args.OriginalSource as ScrollViewer;
|
|
|
+ if (scrollviewer == null)
|
|
|
+ return;
|
|
|
+ if (args != null && PDFViewer != null)
|
|
|
+ {
|
|
|
+ //确保第一次所有item添加完之后再刷新图片
|
|
|
+ //鼠标拖动过程中不拿图
|
|
|
+ if (!isInitaling&& scrollType== ScrollEventType.EndScroll)
|
|
|
+ {
|
|
|
+ //size是拿的DataTemplate的宽高
|
|
|
+ var range = GetRoughFromView(scrollviewer, new Size(208, 320), new Thickness(5, 10, 5, 10));
|
|
|
+ RefreshItemImage(range.Item1, range.Item2 + 1);
|
|
|
+ RefreshBookMarkList();
|
|
|
+ }
|
|
|
+ else//其余滚动的时候,只有滚动暂停后再刷图
|
|
|
+ {
|
|
|
+ if (args.VerticalChange != 0)
|
|
|
+ {
|
|
|
+ timer.Start();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 拖动右侧滑块时触发的事件
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="e"></param>
|
|
|
+ private void ScrollEvent(object e)
|
|
|
+ {
|
|
|
+ var args = (ScrollEventArgs)e;
|
|
|
+ scrollType = args.ScrollEventType;
|
|
|
+ var scroll = CommonHelper.FindVisualParent<ScrollViewer>(args.OriginalSource as ScrollBar);
|
|
|
+ if(args!=null&&PDFViewer!=null&&scroll!=null)
|
|
|
+ {
|
|
|
+ if(scrollType == ScrollEventType.EndScroll)
|
|
|
+ {
|
|
|
+ //size是拿的DataTemplate的宽高
|
|
|
+ var range = GetRoughFromView(scroll, new Size(208, 320), new Thickness(5, 10, 5, 10));
|
|
|
+ RefreshItemImage(range.Item1, range.Item2+1);
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void IsVisibleChangedEvent(object e)
|
|
|
+ {
|
|
|
+ var args = (DependencyPropertyChangedEventArgs)e;
|
|
|
+ if (args == null)
|
|
|
+ return;
|
|
|
+ if ((Visibility)args.NewValue == Visibility.Visible)
|
|
|
+ {
|
|
|
+ GetSourceItems();
|
|
|
+ RefreshBookMarkList();
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void ControlLoad()
|
|
|
+ {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ private void Load(object e)
|
|
|
+ {
|
|
|
+ Debug.Write("Loaded");
|
|
|
+ }
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 从PDFView获取所有Items集合
|
|
|
+ /// </summary>
|
|
|
+ private void GetSourceItems()
|
|
|
+ {
|
|
|
+ PageEditItems.Clear();
|
|
|
+ isInitaling = true;
|
|
|
+ for (int i = 0; i < PDFViewer.Document.PageCount; i++)
|
|
|
+ {
|
|
|
+ PageEditItem item = new PageEditItem();
|
|
|
+ item.PageNumber = i + 1;
|
|
|
+ var pagesize = PDFViewer.Document.GetPageSize(i);
|
|
|
+
|
|
|
+ item.PageSize = $"{pagesize.Width}mm*{pagesize.Height} mm";
|
|
|
+ RefreshItemImage(i,i);
|
|
|
+ PageEditItems.Add(item);
|
|
|
+ }
|
|
|
+ isInitaling = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 刷新书签列表
|
|
|
+ /// </summary>
|
|
|
+ public void RefreshBookMarkList()
|
|
|
+ {
|
|
|
+ if (PDFViewer != null)
|
|
|
+ {
|
|
|
+ var booklist = PDFViewer.Document.GetBookmarkList();
|
|
|
+ if (booklist == null)
|
|
|
+ {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ //获取所有书签的Index集合
|
|
|
+ List<int> marks = new List<int>();
|
|
|
+ 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;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 刷新指定范围的图片
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="startIndex"></param>
|
|
|
+ /// <param name="endIndex"></param>
|
|
|
+ private async void RefreshItemImage(int startIndex,int endIndex)
|
|
|
+ {
|
|
|
+ for (int i = startIndex; i <=endIndex;i++)
|
|
|
+ {
|
|
|
+ if (i <= PDFViewer.Document.PageCount - 1&&i>=0)
|
|
|
+ {
|
|
|
+ //宽高为样式中图片控件宽高
|
|
|
+ await PDFViewer.GetThumbnail(i, 208, 294);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ #region Navigate
|
|
|
+ public bool IsNavigationTarget(NavigationContext navigationContext)
|
|
|
+ {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void OnNavigatedFrom(NavigationContext navigationContext)
|
|
|
+ {
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 从其他页面导航过来的时候会触发
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="navigationContext"></param>
|
|
|
+ public async void OnNavigatedTo(NavigationContext navigationContext)
|
|
|
+ {
|
|
|
+ navigationContext.Parameters.TryGetValue<ViewContentViewModel>(ParameterNames.ViewContentViewModel, out viewContentViewModel);
|
|
|
+ navigationContext.Parameters.TryGetValue<CPDFViewer>(ParameterNames.PDFViewer, out PDFViewer);
|
|
|
+ if (PDFViewer != null)
|
|
|
+ {
|
|
|
+ PDFViewer.OnThumbnailGenerated += PDFViewer_OnThumbnailGenerated;
|
|
|
+ //每次进入前 更新item项,刷新书签列表
|
|
|
+ await Task.Run(() =>
|
|
|
+ {
|
|
|
+ App.Current.Dispatcher.Invoke(() =>
|
|
|
+ {
|
|
|
+ GetSourceItems();
|
|
|
+ });
|
|
|
+ });
|
|
|
+ RefreshBookMarkList();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 获取滑轨的垂直偏移量,结合item总数和Item尺寸以及间隔,来估算实际展示的item范围
|
|
|
+ /// 返回值为页面范围 从1开始
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="scrollViewer"></param>
|
|
|
+ /// <param name="itemSize"></param>
|
|
|
+ /// <param name="itemMargin"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ private Tuple<int, int, int> GetRoughFromView(ScrollViewer scrollViewer, Size itemSize, Thickness itemMargin)
|
|
|
+ {
|
|
|
+ if (PDFViewer == null || PDFViewer.Document == null || scrollViewer == null || scrollViewer.ActualHeight == 0 || scrollViewer.ActualWidth == 0|| scrollViewer.ExtentHeight==0)//视图展开
|
|
|
+ return new Tuple<int, int, int>(0, 0, 0);
|
|
|
+ try
|
|
|
+ {
|
|
|
+ var currentHeight = scrollViewer.ActualHeight;
|
|
|
+ var currentWidth = scrollViewer.ActualWidth;
|
|
|
+ //计算当前窗口大小能显示的行数和列数
|
|
|
+ var columnCount = (int)(currentWidth / (itemSize.Width + itemMargin.Left));
|
|
|
+ var rowCount = (int)Math.Ceiling(currentHeight / (itemSize.Height + itemMargin.Bottom));
|
|
|
+
|
|
|
+ var preItemCount = (int)((scrollViewer.VerticalOffset / scrollViewer.ExtentHeight) * ((PDFViewer.Document.PageCount + columnCount - 1) / columnCount));//滑动百分比*行数 = 大概的垂直位置
|
|
|
+ preItemCount = preItemCount * columnCount;
|
|
|
+ var preEnd = (int)(((scrollViewer.VerticalOffset + scrollViewer.ActualHeight) / scrollViewer.ExtentHeight) * ((PDFViewer.Document.PageCount + columnCount - 1) / columnCount));
|
|
|
+ preEnd = preEnd * columnCount + columnCount - 1;
|
|
|
+
|
|
|
+ var middle = (int)Math.Ceiling(preItemCount + preEnd / 2d);
|
|
|
+
|
|
|
+ return new Tuple<int, int, int>(
|
|
|
+ Math.Max(preItemCount, 0),
|
|
|
+ Math.Min(PageEditItems.Count, preEnd),
|
|
|
+ middle);
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+
|
|
|
+ }
|
|
|
+ return new Tuple<int, int, int>(0, 0, 0);
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 从底层库获取对应页面的图片
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="pageIndex"></param>
|
|
|
+ /// <param name="thumb"></param>
|
|
|
+ /// <param name="w"></param>
|
|
|
+ /// <param name="h"></param>
|
|
|
+ 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
|
|
|
+ {
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|