1、XAML文件中配置好ListBox,在CS文件中為相應的ListBox添加ListBoxItem,如果ListBoxItem的數目較多(超過一屏顯示),當拖動ListBox到底端,然后跳轉到新頁面並返回時ListBox會顯示空白。
XAML文件:
<Grid> <ListBox x:Name="MyListBox" /> </Grid>
CS文件:
private void AddItems() { for (int i = 0; i < 50; i++) { ListBoxItem item = new ListBoxItem(); TextBlock textBlock = new TextBlock(); textBlock.Text = i.ToString(); item.Content = textBlock; MyListBox.Items.Add(item); } }
原因分析:返回原頁面后,ListBox的VerticalOffset與ScrollableHeight值都增加了(超過屏幕高度),所以當用戶回到原頁面不向上拖動ListBox是無法查看到數據內容的。
目前解決方法:修改XAML文件,自定義ListBox的Template。
<Grid> <ListBox x:Name="MyListBox" > <ListBox.Template> <ControlTemplate TargetType="ListBox"> <ScrollViewer BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Foreground="{TemplateBinding Foreground}" Padding="{TemplateBinding Padding}" > <Grid> <ItemsPresenter/> </Grid> </ScrollViewer> </ControlTemplate> </ListBox.Template> </ListBox> </Grid>
2、在ListBox中添加拖動到ListBox底部進行加載數據操作(分頁加載):
常用方法:
1)通過遍歷ListBox的子控件,找到ListBox中自帶的ScrollViewer;
//獲取子類型 public static T FindChildOfType<T>(DependencyObject root) where T : class { var queue = new Queue<DependencyObject>(); queue.Enqueue(root); while (queue.Count > 0) { DependencyObject current = queue.Dequeue(); for (int i = VisualTreeHelper.GetChildrenCount(current) - 1; 0 <= i; i--) { var child = VisualTreeHelper.GetChild(current, i); var typedChild = child as T; if (typedChild != null) { return typedChild; } queue.Enqueue(child); } } return null; }
2)如果ScrollViewer.VerticalOffset >= ScrollViewer.ScrollableHeight,則已經拖動到ListBox底部;
為了簡單,不用去遍歷ListBox獲取ScrollViewer,直接在XAML文件修改Template並添加ScrollViewer的拖動方法。
XAML 文件:
<Grid> <ListBox x:Name="MyListBox" > <ListBox.Template> <ControlTemplate TargetType="ListBox"> <ScrollViewer BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}"
Foreground="{TemplateBinding Foreground}"
Padding="{TemplateBinding Padding}"
ManipulationCompleted="ListBox_ManipulationCompleted"> <Grid> <ItemsPresenter/> </Grid> </ScrollViewer> </ControlTemplate> </ListBox.Template> </ListBox> </Grid>
CS文件:
private void ListBox_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e)
{
ScrollViewer scrollViewer = sender as ScrollViewer;
if (scrollViewer == null)
{
return;
}
// 如果是向下拖動並且已經在ListBox底端
if (e.TotalManipulation.Translation.Y < 0 && scrollViewer.VerticalOffset >= scrollViewer.ScrollableHeight) { // do something } }
3、ListBox分頁加載顯示最新數據:
基本思路:對ListBox中ScrollViewer的VerticalOffset進行修改, 在分頁加載前先記錄VerticalOffset,然后加載完成后根據需要調整VerticalOffset值。
實際操作中發現分頁加載完成后,ListBox中的ScrollViewer的ScrollableHeight並沒有及時發生變化,因此調整VerticalOffset值並不起作用,用戶仍然需要拖動屏幕才能看到最新加載的數據。
由於對ListBox與ScrollViewer內部機制了解不夠,最后只能采用在LayoutUpdated中監控ScrollViewer的ScrollableHeight是否發生變化,如果發生變化則立即調整ScrollViewer的VerticalOffset值。
XAML文件 :
<Grid> <ListBox x:Name="MyListBox" > <ListBox.Template> <ControlTemplate TargetType="ListBox"> <ScrollViewer BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Foreground="{TemplateBinding Foreground}" Padding="{TemplateBinding Padding}"
LayoutUpdated="ListBox_LayoutUpdated" ManipulationCompleted="ListBox_ManipulationCompleted"> <Grid> <ItemsPresenter/> </Grid> </ScrollViewer> </ControlTemplate> </ListBox.Template> </ListBox> </Grid>
CS文件:
private double currentVerticalOffset = 0.0d;
private ScrollViewer myScrollViewer = null;
private double scrollableHeight = 0.0d;
private void ListBox_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e) { ScrollViewer scrollViewer = sender as ScrollViewer; if (scrollViewer == null) { return; }
if (myScrollViewer == null)
{
myScrollViewer = scrollViewer;
} // 如果是向下拖動並且已經在ListBox底端 if (e.TotalManipulation.Translation.Y < 0 && scrollViewer.VerticalOffset >= scrollViewer.ScrollableHeight) {
// 記錄當前偏移值
currentVerticalOffset = scrollViewer.VerticalOffset; // do something } }
private void ListBox_LayoutUpdated(object sender, EventArgs e)
{
if (myScrollViewer != null)
{
if (myScrollViewer.ScrollableHeight > scrollableHeight)
{
if (scrollableHeight > 0)
{
// 設置縱向位置,此處向下拖曳ListBox的實際高度
myScrollViewer.ScrollToVerticalOffset(currentVerticalOffset + this.MyListBox.ActualHeight);
}
scrollableHeight = myScrollViewer.ScrollableHeight;
}
}
}