2013-08-02 39 views
1

我有一个列表框,添加了各种项目。当一个新项目被添加到列表框中时,我需要将该项目滚动到视图中(基本上滚动到底部)。ListBox ScrollIntoView不适用于可变高度的项目

我从How can I have a ListBox auto-scroll when a new item is added?尝试了解决方案,也从this blog post

然而,无论是解决方案的工作,因为我的列表框包含可变高度的项目。如果我把我的列表框项目模板改为固定高度,那么它似乎工作。以下是我的一个项目模板的示例:

<DataTemplate x:Key="StatusMessageTemplate"> 
    <Grid Grid.Column="1" VerticalAlignment="top" Margin="0,5,10,0"> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition Width="*"/> 
      <ColumnDefinition Width="*"/> 
     </Grid.ColumnDefinitions> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="20"></RowDefinition> 
     </Grid.RowDefinitions> 
     <TextBlock Text="{Binding Path=MessageText}" HorizontalAlignment="Left" Grid.Row="0" Grid.Column="0" FontWeight="Bold" Foreground="{DynamicResource LightTextColorBrush}"/> 
     <TextBlock Text="{Binding Path=created_at, StringFormat=t}" Style="{StaticResource Timestamp}" TextWrapping="Wrap" HorizontalAlignment="Right" Grid.Row="0" Grid.Column="1"/> 
    </Grid> 
</DataTemplate> 

如何让新项目滚动到视图中而不管其高度如何?

+0

当你调用ScrollIntoView(),你确定你有你的列表框项目的顶级FrameworkElement的一个参考,而的不是一个一个辅助函数ListBoxItem的子控件?我不确定这是否会有所作为,但如果确实如此,它可能会完全符合你的要求。 – Steve

+0

这两个班我尝试使用listitem,所以我很确定这不是问题。 –

回答

1

我想我已经找到了问题。直到显示后才会计算可变高度项目。所以我添加一个定时器来调用ScrollIntoView函数。但即使这样也行不通,所以我使用VisualTreeHelper来查找ScrollViewer对象并将其强制到特定行。这是代码。

 System.Windows.Threading.DispatcherTimer dTimer = new System.Windows.Threading.DispatcherTimer(); 
    dTimer.Interval = new TimeSpan(0, 0, 0, 0, 200); // 200 Milliseconds 
    dTimer.Tick += new EventHandler(
     (seder, ea) => 
     { 
      //Verses.ScrollIntoView(Verses.Items[itemIndex]); 
      for (int i = 0; i < VisualTreeHelper.GetChildrenCount(Verses); i++) 
      { 
       DependencyObject depObj = VisualTreeHelper.GetChild(Verses, i); 
       if (depObj is ScrollViewer) 
       { 
       ScrollViewer sv = depObj as ScrollViewer; 
       sv.ScrollToVerticalOffset(itemIndex); // Zero based index 
       break; 
       } 
      } 
      dTimer.Stop(); 
     }); 
    dTimer.Start(); 
2

我需要滚动该项目到视图(基本上滚动到底部)。

ScrollIntoView表现奇怪,当列表框具有可变高度的项目。

如果唯一目的是滚动到底部,则可以直接访问滚动查看器并滚动到最大可能偏移量,如下所示。

var scrollViewer = GetDescendantByType(ListBoxChats, typeof(ScrollViewer)) as ScrollViewer; 
scrollViewer.ScrollToVerticalOffset(Double.MaxValue); 

public static Visual GetDescendantByType(Visual element, Type type) 
{ 
    if (element == null) 
    { 
     return null; 
    } 
    if (element.GetType() == type) 
    { 
     return element; 
    } 
    Visual foundElement = null; 
    if (element is FrameworkElement) 
    { 
     (element as FrameworkElement).ApplyTemplate(); 
    } 
    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(element); i++) 
    { 
     Visual visual = VisualTreeHelper.GetChild(element, i) as Visual; 
     foundElement = GetDescendantByType(visual, type); 
     if (foundElement != null) 
     { 
      break; 
     } 
    } 
    return foundElement; 
} 

GetDescendantByType是punker76写@another SO post