PageEditContent.xaml.cs 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. using PDF_Office.EventAggregators;
  2. using PDF_Office.Tools;
  3. using Prism.Events;
  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;
  10. using System.Windows.Controls;
  11. using System.Windows.Controls.Primitives;
  12. using System.Windows.Data;
  13. using System.Windows.Documents;
  14. using System.Windows.Input;
  15. using System.Windows.Media;
  16. using System.Windows.Media.Imaging;
  17. using System.Windows.Navigation;
  18. using System.Windows.Shapes;
  19. using System.Windows.Threading;
  20. namespace PDF_Office.Views.PageEdit
  21. {
  22. /// <summary>
  23. /// PageEditContent.xaml 的交互逻辑
  24. /// </summary>
  25. public partial class PageEditContent : UserControl
  26. {
  27. /// <summary>
  28. /// 用于通知刷新图片的事件
  29. /// 因为目前的图片刷新策略依赖很多UI事件判断,因为将主要判断逻辑放在UI层,VM负责图片刷新,非必要情况尽量不要采用这种形式
  30. /// </summary>
  31. private IEventAggregator eventor;
  32. /// <summary>
  33. /// 暂存的唯一索引值,用于区分多页签
  34. /// </summary>
  35. private string unicode;
  36. /// <summary>
  37. /// 是否是加载时第一次触发滚动
  38. /// </summary>
  39. private bool isFirstScrollChange = true;
  40. /// <summary>
  41. /// 用于判断滚轮停止的计时器
  42. /// </summary>
  43. private DispatcherTimer timer = new DispatcherTimer();
  44. /// <summary>
  45. /// 记录当前滑块的状态
  46. /// </summary>
  47. private ScrollEventType scrolltype = ScrollEventType.EndScroll;
  48. public PageEditContent()
  49. {
  50. InitializeComponent();
  51. }
  52. public PageEditContent(IEventAggregator eventAggregator) :this()
  53. {
  54. eventor = eventAggregator;
  55. unicode = App.mainWindowViewModel.SelectedItem.Unicode;
  56. timer.Interval = TimeSpan.FromSeconds(0.3);
  57. timer.Tick += Timer_Tick;
  58. }
  59. private void Timer_Tick(object sender, EventArgs e)
  60. {
  61. PulishEvent();
  62. timer.Stop();
  63. }
  64. /// <summary>
  65. /// 每次显示的时候就触发事件,刷新所有图片
  66. /// </summary>
  67. /// <param name="sender"></param>
  68. /// <param name="e"></param>
  69. private void PageEdit_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
  70. {
  71. if((bool)e.NewValue)
  72. {
  73. PulishEvent();
  74. }
  75. }
  76. /// <summary>
  77. /// 发布事件
  78. /// </summary>
  79. private void PulishEvent()
  80. {
  81. var range = GetRoughFromView(ListPageEdit, new Size(208, 320), new Thickness(5, 10, 5, 10));
  82. eventor.GetEvent<PageEditRefreshEvent>().Publish(new PageEditRefreshEventArgs() { Unicode = unicode, PageRange = range });
  83. }
  84. /// <summary>
  85. /// 获取滑轨的垂直偏移量,结合item总数和Item尺寸以及间隔,来估算实际展示的item范围
  86. /// 返回值为页面范围 从1开始
  87. /// </summary>
  88. /// <param name="view"></param>
  89. /// <param name="itemSize"></param>
  90. /// <param name="itemMargin"></param>
  91. /// <returns></returns>
  92. private Tuple<int, int, int> GetRoughFromView(ListBox view, Size itemSize, Thickness itemMargin)
  93. {
  94. //var scrollViewer = GetScrollHost(view);
  95. var scrollViewer = CommonHelper.FindVisualChild<ScrollViewer>(view);
  96. if (scrollViewer == null || scrollViewer.ActualHeight == 0 || scrollViewer.ActualWidth == 0)//视图展开
  97. return new Tuple<int, int, int>(0, 0, 0);
  98. try
  99. {
  100. var currentHeight = scrollViewer.ActualHeight - view.Padding.Top;
  101. var currentWidth = scrollViewer.ActualWidth;
  102. //计算当前窗口大小能显示的行数和列数
  103. var columnCount = (int)(currentWidth / (itemSize.Width + itemMargin.Left));
  104. var rowCount = (int)Math.Ceiling(currentHeight / (itemSize.Height + itemMargin.Bottom));
  105. var preItemCount = (int)((scrollViewer.VerticalOffset / scrollViewer.ExtentHeight) * ((view.Items.Count + columnCount - 1) / columnCount));//滑动百分比*行数 = 大概的垂直位置
  106. preItemCount = preItemCount * columnCount;
  107. var preEnd = (int)(((scrollViewer.VerticalOffset + scrollViewer.ActualHeight) / scrollViewer.ExtentHeight) * ((view.Items.Count + columnCount - 1) / columnCount));
  108. preEnd = preEnd * columnCount + columnCount - 1;
  109. var middle = (int)Math.Ceiling(preItemCount + preEnd / 2d);
  110. return new Tuple<int, int, int>(
  111. Math.Max(preItemCount, 0),
  112. Math.Min(view.Items.Count, preEnd),
  113. middle);
  114. }
  115. catch (Exception ex)
  116. {
  117. }
  118. return new Tuple<int, int, int>(0, 0, 0);
  119. }
  120. /// <summary>
  121. /// 获取listbox里的ScrollViewer对象
  122. /// 留意如果有重写ListBox对象,该方法可能无效
  123. /// </summary>
  124. /// <param name="listBox"></param>
  125. /// <returns></returns>
  126. private ScrollViewer GetScrollHost(ListBox listBox)
  127. {
  128. if (VisualTreeHelper.GetChildrenCount(listBox) > 0)
  129. {
  130. int s = VisualTreeHelper.GetChildrenCount(listBox);
  131. Border border = VisualTreeHelper.GetChild(listBox, 0) as Border;
  132. if (border != null)
  133. {
  134. return VisualTreeHelper.GetChild(border, 0) as ScrollViewer;
  135. }
  136. }
  137. return null;
  138. }
  139. private void ListPageEdit_ScrollChanged(object sender, ScrollChangedEventArgs e)
  140. {
  141. if (isFirstScrollChange)
  142. {
  143. PulishEvent();//第一次加载时触发的Scollchange 直接刷新界面,减少白板显示时间
  144. isFirstScrollChange = false;
  145. return;
  146. }
  147. else
  148. {
  149. if (e.VerticalChange != 0)
  150. timer.Start();//暂时找不到比较好的 判断Scroller停止的方法,先用计时器粗略判断
  151. }
  152. }
  153. private void ListPageEdit_Scroll(object sender, System.Windows.Controls.Primitives.ScrollEventArgs e)
  154. {
  155. scrolltype = e.ScrollEventType;
  156. if (scrolltype != System.Windows.Controls.Primitives.ScrollEventType.EndScroll)
  157. {
  158. timer.Stop();
  159. return;
  160. }
  161. PulishEvent();
  162. }
  163. }
  164. }