wpf listbox 滾動翻頁功能
阿新 • • 發佈:2019-01-30
最近有個需求,需要通過 listbox滾動實現翻頁功能。查了下資料 總結如下。
方案一:利用ScrollViewer.ScrollChanged事件來實現當偏移量到底部時,進行相應操作。
xaml中
<ListBox BorderBrush="Red" Grid.Column="0" ItemsSource="{Binding SchoolNoticeList}" ItemTemplate="{StaticResource listboxitemT}" ScrollViewer.ScrollChanged="ListBox_ScrollChanged"/>
對應的事件
按照微軟(https://msdn.microsoft.com/zh-cn/library/ms612678)的解釋private void ListBox_ScrollChanged(object sender, ScrollChangedEventArgs e) { ScrollViewer sv = e.OriginalSource as ScrollViewer; ListScrollWndViewModel vm = this.DataContext as ListScrollWndViewModel; if (sv != null) { Console.WriteLine(e.VerticalOffset.ToString()); if(IsVerticalScrollBarAtButtom(sv)) { vm.MsgTest = "已到底部"; } else{ vm.MsgTest="未到底部"; } } } public bool IsVerticalScrollBarAtButtom(ScrollViewer s) { bool isAtButtom = false; double dVer = s.VerticalOffset; double dViewport = s.ViewportHeight; double dExtent = s.ExtentHeight; Console.WriteLine("dVer:"+dVer+" dViewport:"+dViewport+" dExtent:"+dExtent); if (dVer != 0) { if (dVer + dViewport == dExtent) { isAtButtom = true; } else { isAtButtom = false; } } else { isAtButtom = false; } if (s.VerticalScrollBarVisibility == ScrollBarVisibility.Disabled || s.VerticalScrollBarVisibility == ScrollBarVisibility.Hidden) { isAtButtom = true; } return isAtButtom; }
VerticalOffset是獲取包含滾動內容的垂直偏移量的值。,viewportheight是獲取包含內容視區垂直大小的值。ExtentHeight 獲取包含盤區垂直大小的一個值。
利用圖來解釋一下
這是一個20個數據長度(從0到20)長度的listbox,可以看出VerticalOffset其實就是從上往下覆蓋的元素數量(4),viewportheight是控制元件可供人看到的元素數量(10=13-4+1) ExtentHeight是總的元素數量(20)。通過改變視窗大小,viewportheight會跟隨改變,拖動滾動條,VerticalOffset也會跟著改變。判斷滾動到底部的條件 自然就是
VerticalOffset+viewportheight==ExtentHeight
但這種方式 有兩個問題
一個是如何向前翻頁,如果簡單的以VerticalOffset==0 來判斷,當初始化的時候,就會發現scorllchanged就會觸發,並且VerticalOffset等於0
二是當最後一頁資料較少,滾動條不出現時,scorllchanged就永遠不會被觸發,也就是說最後一頁無法向前翻。
方案二:
直接利用previewmousewheel來判斷向前向後翻轉。
xaml
<ListBox BorderBrush="Green" Grid.Column="1" ItemsSource="{Binding SchoolNoticeList}" ItemTemplate="{StaticResource listboxitemT}" PreviewMouseWheel="ListBox_PreviewMouseWheel" />
對應的響應事件
private void ListBox_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
ListScrollWndViewModel vm = this.DataContext as ListScrollWndViewModel;
Console.WriteLine(e.Delta);
if (e.Delta > 0)
{
Console.WriteLine("正在向上滾動滑輪");
vm.MsgTest = "正在向上滾動滑輪";
}
else
{
Console.WriteLine("正在向下滾動滑輪");
vm.MsgTest = "正在向下滾動滑輪";
}
}
這種方法的劣勢在於頁面上資料不能太多(不能出現滾動條),否則被覆蓋的資料不會顯現出來。
把兩種結合起來,也許會更好,利用previewmousewheel來觸發事件,當滾動條偏移量為0,則向上翻頁,滾動條到底部則 向下翻頁。
首先需要獲得listbox中的scrollviewer
Decorator border = VisualTreeHelper.GetChild(listbox3, 0) as Decorator;
if (border != null)
{
scrollViewer = border.Child as ScrollViewer;
}
然後在previewmousewheel裡面進行事件處理
private void ListBox3_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
ListScrollWndViewModel vm = this.DataContext as ListScrollWndViewModel;
Console.WriteLine(e.Delta);
if (e.Delta > 0)
{
if (scrollViewer.VerticalOffset == 0)
{
Pre(); }
}
else
{
if (scrollViewer.VerticalOffset + scrollViewer.ViewportHeight == scrollViewer.ExtentHeight)
{
Next();
scrollViewer.ScrollToTop();
}
}
}