裂隙动水注浆模拟技术与工程应用
2026/10/15 8:33:22
原写法的写法:
LogList.ScrollIntoView(LogList.Items[LogList.Items.Count - 1]);数据不滚动
这个 ListBox 开了虚拟化:
<ListBox x:Name="LogList" VirtualizingPanel.IsVirtualizing="True" VirtualizingPanel.VirtualizationMode="Recycling">ScrollIntoView(item)内部是两步:① 找到 item 对应的容器(ListBoxItem);② 按容器位置滚视口。而 UI 虚拟化的核心是只给可视区内的项生成容器——最新一行恰在视口外,容器根本不存在。于是:要显示它就得滚 → 要滚就得知道位置 → 要知道位置就得先有容器 →循环依赖,滚动被无限挂起。
private void OnLinesChanged(object sender, NotifyCollectionChangedEventArgs e) { if (e.Action != NotifyCollectionChangedAction.Add) return; if (DataContext is not DebugPanelViewModel vm || !vm.AutoScroll) return; // 修复:不用 ListBox.ScrollIntoView —— 虚拟化列表里它要等目标项的容器生成, // 而最新一行在视口外容器永远不会生成,滚动会被无限期挂起。 // 直接让 ListBox 内部的 ScrollViewer 滚到底,并延到下一轮 UI(此时新行已进入 Items)。 Dispatcher.BeginInvoke(new Action(() => { GetScrollViewer(LinesControl)?.ScrollToEnd(); }), DispatcherPriority.Loaded); }// 递归找 ListBox 内部的 ScrollViewer private static ScrollViewer GetScrollViewer(DependencyObject d) { if (d is ScrollViewer sv) return sv; for (int i = 0; i < VisualTreeHelper.GetChildrenCount(d); i++) { if (GetScrollViewer(VisualTreeHelper.GetChild(d, i)) is ScrollViewer found) return found; } return null; }