为什么不'ScrollIntoView从来没有工作过

本文关键字:从来没有 工作 ScrollIntoView 为什么不 | 更新日期: 2023-09-27 18:16:57

我正试图滚动到视图,以便在垂直listview中的最后一个项目总是显示,但ListView.ScrollIntoView()从来没有工作。

I have try:

button1_Click(object sender, EventArgs e)
{
            activities.Add(new Activities()
            {
                Time = DateTime.Now,
                Message = message
            });
            ActivityList.ItemsSource = activities;
            // Go to bottom of ListView.
            ActivityList.SelectedIndex = ActivityList.Items.Count;
            ActivityList.ScrollIntoView(ActivityList.SelectedIndex);
}

我也试过了:

ActivityList.ScrollIntoView(ActivityList.Items.Count),和ActivityList.ScrollIntoView(ActivityList.Items.Count + 1);,但没有工作

请帮助。这真的很烦人。在这种情况下,文档并不是很有帮助。

为什么不'ScrollIntoView从来没有工作过

当方法需要item对象时,您正在传递索引。试着滚动到选定的项目。

ActivityList.ScrollIntoView(ActivityList.SelectedItem);

如果你想滚动到最后一项,可以使用

ActivityList.ScrollIntoView(ActivityList.Items[ActivityList.Items.Count - 1]);

这与内部列表表示有关,即,当您调用ScrollIntoView().时,项目尚未就绪经过多次尝试,这就是我最终提出的,这似乎有效:将两个处理程序附加到每个ListBox/ListView:

<ListBox x:Name="YourList" ... Loaded="YourList_Loaded" SelectionChanged="YourList_SelectionChanged">

void YourList_Loaded(object sender, RoutedEventArgs e) {
  if (YourList.SelectedItem != null)
    YourList.ScrollIntoView(YourList.SelectedItem);
}
void YourList_SelectionChanged(object sender, SelectionChangedEventArgs e) {
  if (YourList.SelectedItem != null)
    YourList.ScrollIntoView(YourList.SelectedItem);
}

不可缺少的第二个处理程序。你不能在设置完选中的项目后立即调用ScrollIntoView(),它还没有准备好。你必须允许列表通知你,当它实际上已经改变了项目。第一个处理程序取决于具体情况,如果在初始加载列表内容后选择显示有问题,您可能也需要它。

ActivityList.ScrollIntoView(ActivityList.Items[ActivityList.Items.Count - 1]);的问题类似的"解决方案",至少从我所经历的,是当ListBox包含相同的项目不止一次,它跳转到它找到的第一个,即最低的索引。所以,它不关心你输入的项的索引,它只查找该项并选择第一个。

我还没有找到一个解决方案,但我现在采取的方法是插入而不是添加项目。在最初的海报案例中,我认为这会导致:

activities.Insert(0, new Activities()
        {
            Time = DateTime.Now,
            Message = message
        });

或:

ActivityList.Items.Insert(0, new Activities()
        {
            Time = DateTime.Now,
            Message = message
        });

这会导致每个新条目都被插入到顶部,因此ScrollIntoView甚至不需要被调用

这是一个旧的帖子,但由于这里的答案都不适合我的情况,我想添加我的实现。我在这里找到了解决方案:[https://social.msdn.microsoft.com/Forums/vstudio/en-US/8a745550-4360-4b53-85f5-032f8f46e2cc/listview-scrollintoview-not-working-with-a-observablecollection?forum=wpf][1]

((INotifyCollectionChanged)lvLogs.Items).CollectionChanged += ListView_CollectionChanged;
private void ListView_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
    ScrollToEnd(this.lvLogs);
}
private void ListView_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if ((e.Action == NotifyCollectionChangedAction.Add) && (e.NewItems != null))
            {
                try 
                {
                    ScrollToEnd(this.lvLogs);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.ToString(), "Error updating list view", MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
        }
public void ScrollToEnd(ListView _ListView)
{
    ScrollViewer _ScrollViewer = GetDescendantByType(_ListView, typeof(ScrollViewer)) as ScrollViewer;
    _ScrollViewer.ScrollToEnd();
}
public 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;
}

您正在分配项目的索引,并且列表框期望项目本身。试试这样做:

 var activity = new Activities()
        {
            Time = DateTime.Now,
            Message = message
        };
 activities.Add(activity);
 ActivityList.ItemsSource = activities;
 ActivityList.ScrollIntoView(activity);

这是一篇老文章,但我在Windows Store应用程序中遇到了同样的问题,并发现以下工作:

    private void PagesListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        pageListView.UpdateLayout();
        pageListView.ScrollIntoView(pageListView.SelectedItem);
    }

欢呼,保罗

我不确定这个主题是否仍然感兴趣,但我无法在我的LISTBOX上获得上述选项。我在某个地方读到,不平等的项目大小也停止了卷轴的工作。我确实得到了下面的Powershell代码工作;'UpdateLayout()'似乎很重要:

$zItemsCount = $ListBox.Items.Count - 1
Write-Host -ForegroundColor Cyan "ListBox Items Count - 1:" $zItemsCount
(0..$zItemsCount) | ForEach-Object {
  $ListBox.SelectedIndex = $_
  $ListBox.UpdateLayout()
  $ListBox.ScrollIntoView($ListBox.SelectedItem)
  }#-EndOf: each item -----

根据keyboardP在2013年6月5日14:37的声明:https://stackoverflow.com/a/16942650/2717521

如果仍然不起作用,尝试调用ActivityList.UpdateLayout();在ScrollIntoView方法之前。

我有一个类似的问题之间,我最初认为,相同的datagrid。第一个会ScrollIntoView没有任何问题,第二个拒绝这样做,无论如何,除非我触发UpdateLayout。结果是我也分组了第二个DataGrid:

        mycollection.GroupDescriptions.Clear();
        mycollection.GroupDescriptions.Add(new PropertyGroupDescription("PART"));
        datagrid_parts.ItemsSource = mycollection.View;

显然,如果你的DataGrid是分组,ScrollViewer不能得到正确的"视觉"空间,因为一些可见的区域留在GroupItem组内。值:https://social.msdn.microsoft.com/forums/vstudio/en us/b809f5ae - 08 - e7 - 415 f - 9 - e86 fc0086cb49e7/datagrid scrollintoview -——不把-鉴于-项目- - - -使用虚拟化和grouping?forum=wpf

可能发生这种情况的另一个原因是,ItemsPanel默认情况下是VirtualizingStackPanel,它已经将项目虚拟化了。如果你不需要虚拟化,因为你只有相对较少的项目,那么你可以使用正常的StackPanel作为你的ItemsPanel。

<ListBox>
  <ItemsControl.ItemsPanel>
    <ItemsPanelTemplate>
      <StackPanel Orientation="Vertical" />
    </ItemsPanelTemplate>
  </ItemsControl.ItemsPanel>
</ListBox>

我遇到的问题与此类似。我以编程方式添加到ListBox中,需要添加的最后一项是可见的。在尝试了各种方法之后,我发现下面的方法是最简单和最好的

lstbox.Items.MoveCurrentToLast();
lstbox.ScrollIntoView(lstbox.Items.CurrentItem);

直接调用方法UpdateLayout…

UpdateLayout();
ActivityList.ScrollIntoView(ActivityList.Items[ActivityList.Items.Count - 1]);

This will work…

或者更简单的方法…只需编译app:),它将工作没有UpdateLayot()