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;
}
}
}