14

I am trying to scroll into view so that the very last item in a vertical listivew is always showing, but ListView.ScrollIntoView() never works.

I have tried:

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

I have also tried:

ActivityList.ScrollIntoView(ActivityList.Items.Count), and ActivityList.ScrollIntoView(ActivityList.Items.Count + 1); but nothing is working.

Please help. This is really annoying. And the documentation isn't very helpful in this case.

4

11 回答 11

20

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

ActivityList.ScrollIntoView(ActivityList.SelectedItem);

如果要滚动到最后一项,可以使用此

ActivityList.ScrollIntoView(ActivityList.Items[ActivityList.Items.Count - 1]);
于 2013-06-05T14:30:17.250 回答
10

它与内部列表表示有关,即当您调用时,项目尚未到位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()立即调用,它还没有准备好。您必须允许列表在实际更改项目时通知您。第一个处理程序取决于具体情况,如果在初始加载列表内容后出现选择时出现问题,您可能也需要它。

于 2014-10-09T09:28:29.073 回答
4

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。

于 2015-06-23T09:56:30.750 回答
3

这是一篇旧文章,但由于这里的答案都不适用于我的案例,我想添加我的实现。我在这里找到了解决方案:[ https://social.msdn.microsoft.com/Forums/vstudio/en-US/8a745550-4360-4b53-85f5-032f8f46e2cc/listview-scrollintoview-not-working-with-a-observablecollection ?论坛=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;
}

对我来说,它完美无缺。

于 2015-09-18T01:02:50.247 回答
1

您正在分配项目的索引,并且列表框需要项目本身。尝试这样的事情:

 var activity = new Activities()
        {
            Time = DateTime.Now,
            Message = message
        };

 activities.Add(activity);

 ActivityList.ItemsSource = activities;
 ActivityList.ScrollIntoView(activity);
于 2013-06-05T14:32:30.970 回答
0

这是一篇旧帖子,但我在 Windows Store 应用程序中遇到了同样的问题,发现以下方法有效:

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

干杯,保罗

于 2016-04-15T04:14:24.257 回答
0

发生这种情况的另一个原因是该项目已被 ItemsPanel 虚拟化,默认情况下是 VirtualizingStackPanel。如果您不需要虚拟化,因为您只有相对少量的项目,那么您可以使用普通的 StackPanel 作为您的 ItemsPanel。

<ListBox>
  <ItemsControl.ItemsPanel>
    <ItemsPanelTemplate>
      <StackPanel Orientation="Vertical" />
    </ItemsPanelTemplate>
  </ItemsControl.ItemsPanel>
</ListBox>
于 2021-05-06T15:30:21.797 回答
0

我不确定这个主题是否仍然令人感兴趣,但我无法在我的 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 -----
于 2019-04-24T13:58:09.160 回答
0

根据keyboardP在 2013 年 6 月 5 日 14:37 在这里所说的:https ://stackoverflow.com/a/16942650/2717521

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

我最初认为相同的 DataGrids 之间有一个类似的问题。第一个将 ScrollIntoView 没有任何问题,第二个无论如何都拒绝这样做,除非我触发了 UpdateLayout。事实证明,我也在对第二个 DataGrid 进行分组:

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

显然,如果您的 DataGrid 正在分组,则 ScrollViewer 无法获得正确的“视觉”空间,因为某些可见区域作为 GroupItem 保留在 Group 内。参考: https ://social.msdn.microsoft.com/Forums/vstudio/en-US/b809f5ae-08e7-415f-9e86-fc0086cb49e7/datagrid-scrollintoview-does-not-bring-given-item-into-view-何时使用虚拟化和分组?forum=wpf

于 2020-04-02T11:10:12.763 回答
-1

只需调用方法 UpdateLayout...

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

这将工作...

或者更简单的方法......只需编译应用程序:),它可以在没有 UpdateLayot() 的情况下工作

于 2017-06-17T17:52:53.613 回答
-1

我面临的问题是相似的。我以编程方式添加到 ListBox 并需要添加的最后一项可见。在捆绑了各种方法后,我发现以下是最简单和最好的

lstbox.Items.MoveCurrentToLast();
lstbox.ScrollIntoView(lstbox.Items.CurrentItem);
于 2016-03-22T08:26:04.617 回答