using PDF_Office.EventAggregators;
using PDF_Office.Helper;
using PDF_Office.Model.PageEdit;
using Prism.Events;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
namespace PDF_Office.Views.PageEdit
{
///
/// PageEditContent.xaml 的交互逻辑
///
public partial class PageEditContent : UserControl
{
///
/// 用于通知刷新图片的事件
/// 因为目前的图片刷新策略依赖很多UI事件判断,因为将主要判断逻辑放在UI层,VM负责图片刷新,非必要情况尽量不要采用这种形式
///
private IEventAggregator eventor;
///
/// 暂存的唯一索引值,用于区分多页签
///
private string unicode;
///
/// 是否是加载时第一次触发滚动
///
private bool isFirstScrollChange = true;
///
/// 用于判断滚轮停止的计时器
///
private DispatcherTimer timer = new DispatcherTimer();
///
/// 记录当前滑块的状态
///
private ScrollEventType scrolltype = ScrollEventType.EndScroll;
public PageEditContent()
{
InitializeComponent();
}
public PageEditContent(IEventAggregator eventAggregator) :this()
{
eventor = eventAggregator;
unicode = App.mainWindowViewModel.SelectedItem.Unicode;
timer.Interval = TimeSpan.FromSeconds(0.3);
timer.Tick += Timer_Tick;
//订阅页面刷新事件
eventor.GetEvent().Subscribe(OneNotifyEvent, e => e.Unicode == unicode);
}
private void Timer_Tick(object sender, EventArgs e)
{
PulishEvent();
timer.Stop();
}
private void OneNotifyEvent(PageEditNotifyEventArgs e)
{
PulishEvent();
}
#region UI事件
///
/// 每次显示的时候就触发事件,刷新所有图片
///
///
///
private void PageEdit_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if((bool)e.NewValue)
{
//当前页面没有发生变化时,刷新图片 这种情况下会拿两次图,需要留意
PulishEvent();
//当前页面发生变化时通过ScrollChanged事件来刷新图片
isFirstScrollChange = true;
}
}
///
/// 鼠标滚轮滚动时触发的事件
///
///
///
private void ListPageEdit_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
if (isFirstScrollChange)
{
PulishEvent();//第一次加载时触发的Scollchange 直接刷新界面,减少白板显示时间
isFirstScrollChange = false;
return;
}
else
{
if (e.VerticalChange != 0)
timer.Start();//暂时找不到比较好的 判断Scroller停止的方法,先用计时器粗略判断
}
}
///
/// 拖动右侧滑块时触发的事件
///
///
///
private void ListPageEdit_Scroll(object sender, System.Windows.Controls.Primitives.ScrollEventArgs e)
{
scrolltype = e.ScrollEventType;
if (scrolltype != System.Windows.Controls.Primitives.ScrollEventType.EndScroll)
{
timer.Stop();
return;
}
PulishEvent();
}
#endregion
#region 方法
///
/// 发布事件
///
private void PulishEvent()
{
var itemSize = (ListPageEdit.Items[0] as PageEditItem).ItemSize;
var range = GetRoughFromView(ListPageEdit, itemSize, new Thickness(5, 10, 5, 10));
eventor.GetEvent().Publish(new PageEditRefreshEventArgs() { Unicode = unicode, PageRange = range });
}
///
/// 获取滑轨的垂直偏移量,结合item总数和Item尺寸以及间隔,来估算实际展示的item范围
/// 返回值为页面范围 从1开始
///
///
///
///
///
private Tuple GetRoughFromView(ListBox view, Size itemSize, Thickness itemMargin)
{
//var scrollViewer = GetScrollHost(view);
var scrollViewer = CommonHelper.FindVisualChild(view);
if (scrollViewer == null || scrollViewer.ActualHeight == 0 || scrollViewer.ActualWidth == 0)//视图展开
return new Tuple(0, 0, 0);
try
{
var currentHeight = scrollViewer.ActualHeight - view.Padding.Top;
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) * ((view.Items.Count + columnCount - 1) / columnCount));//滑动百分比*行数 = 大概的垂直位置
preItemCount = preItemCount * columnCount;
var preEnd = (int)(((scrollViewer.VerticalOffset + scrollViewer.ActualHeight) / scrollViewer.ExtentHeight) * ((view.Items.Count + columnCount - 1) / columnCount));
preEnd = preEnd * columnCount + columnCount - 1;
var middle = (int)Math.Ceiling(preItemCount + preEnd / 2d);
return new Tuple(
Math.Max(preItemCount, 0),
Math.Min(view.Items.Count, preEnd),
middle);
}
catch { }
return new Tuple(0, 0, 0);
}
///
/// 获取listbox里的ScrollViewer对象
/// 留意如果有重写ListBox对象,该方法可能无效
///
///
///
private ScrollViewer GetScrollHost(ListBox listBox)
{
if (VisualTreeHelper.GetChildrenCount(listBox) > 0)
{
int s = VisualTreeHelper.GetChildrenCount(listBox);
Border border = VisualTreeHelper.GetChild(listBox, 0) as Border;
if (border != null)
{
return VisualTreeHelper.GetChild(border, 0) as ScrollViewer;
}
}
return null;
}
#endregion
///
/// 输入框显示时,自动获取焦点
///
///
///
private void TextBox_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if((bool)e.NewValue)
{
(sender as Control).Focus();
}
}
}
}