WP7 listbox 总结

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;
    }
  }
}
复制代码
http://www.cnblogs.com/IronSword/archive/2012/04/12/2444210.html
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章