Bắt sự kiện ScrollChanged
Trong các controller của WPF như
DataGrid
, ListView
... để bắt sự kiện khi cuộn thì khai báo bắt sự kiện bằng thuộc tính ScrollViewer.ScrollChanged
Ví dụ ListView sau sẽ bắt sự kiện khi các phần tử của nó cuộn lên/xuống
<ListView Name="listview" ScrollViewer.ScrollChanged="listview_ScrollChanged" />
Trong đó
listview_ScrollChanged
là code xử lý khi nhận được sự kiện, nó có cấu trúc dạng:private void ScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e) { //... }
Bật/tắt bắt sự kiện ScrollChanged sử dụng AddHandler/RemoveHandler
Ngoài cách khai báo trong XAML như trên, nếu muốn linh hoạt hơn, có thể dễ dàng kích hoạt khi nào muốn bắt sự kiện
ScrollChanged
, khi nào không muốn bắt thì dùng cách sau, vì dụ đã khai báo một ListView tên listview
: 1) Khai báo một Delegate lưu giữ xử lý sự kiện
private Delegate listviewscrollhandler;
2) Khai báo một phương thức giống với cấu trúc nhận sự kiện
ScrollViewer.ScrollChangedEvent
private void ScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e) { //code như nhận được ScrollChanged }
3) Khi khởi tạo Controller, thì khởi tạo giá trị hàm gán cho Delegate trên
listviewscrollhandler = new ScrollChangedEventHandler(ScrollViewer_ScrollChanged);
4) Khi nào muốn
listview
bắt đầu nhận sự kiện ScrollChanged thì thêm vào:listview.AddHandler(ScrollViewer.ScrollChangedEvent, listviewscrollhandler);
5) Khi nào muốn
listview
không nhận ScrollChanged thì thêm vào:listview.RemoveHandler(ScrollViewer.ScrollChangedEvent, listviewscrollhandler);
Nhận biết khi phần tử cuối trong ListView, DataGrid ... cuộn tới phần tử cuối
Khi phần tử cuối được cuộn đến, nghĩa là nó đang hiện thị trên giao diện - vậy chỉ cần kiểm tra việc này:
private void ScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e) { if ((e.VerticalChange > 0)) //Cuộn xuống { object item_end = listview.Items[listview.Items.Count - 1]; ListViewItem listview_item_end = (ListViewItem)listview.ItemContainerGenerator.ContainerFromItem(item_end); if (item_end != null) { //CÓ CUỘN TỚI PHẦN TỬ CUỐI } } }
Ví dụ
Sử dụng ListView, hiện thị khởi đầu 100 phần tử. Khi cuộn tới phần tử cuối thì đổ thêm 100 phần tử nữa vào ListView ..., code như sau:
Window.xaml
<Window x:Class="ScrollEndItem.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:ScrollEndItem" mc:Ignorable="d" Title="MainWindow" Height="450" Width="300"> <ListView Name="listview" /> </Window>
Window.xaml.cs
namespace ScrollEndItem { public partial class MainWindow : Window { private Delegate listviewscrollhandler; public MainWindow() { InitializeComponent(); //Tạo Delegate nhận sự kiện khi cuộn listviewscrollhandler = new ScrollChangedEventHandler(ScrollViewer_ScrollChanged); //Bắt sự kiện ScrollViewer.ScrollChangedEvent listview.AddHandler(ScrollViewer.ScrollChangedEvent, listviewscrollhandler); Add100item(); } void Add100item() { for (int i = 0; i < 100; i++) { listview.Items.Add(new ListViewItem() { Content = $"Phần tử {listview.Items.Count + 1}" }); } } private void ScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e) { //Không bắt scroll khi đang xử lý listview.RemoveHandler(ScrollViewer.ScrollChangedEvent, listviewscrollhandler); if ((e.VerticalChange > 0)) { object item_end = listview.Items[listview.Items.Count - 1]; ListViewItem listview_item_end = (ListViewItem)listview.ItemContainerGenerator.ContainerFromItem(item_end); if (listview_item_end != null) { Add100item(); listview.UpdateLayout(); } } //Thêm scroll sau khi xử lý xong listview.AddHandler(ScrollViewer.ScrollChangedEvent, listviewscrollhandler); } } }
Chạy ví dụ trên, mỗi khi ListView cuộn tới cuối, sẽ có thêm 100 phần tử thêm vào.