如何阻止UWP TreeView选中项时的自动垂直滚动行为
禁用UWP TreeView选中项自动滚动到视图中间的方案
你提到的WPF平台RequestBringIntoView事件拦截方案在UWP中不适用,是因为UWP没有暴露该事件的EventSetter支持。UWP平台下所有元素滚动到可视区域的逻辑,最终都是通过冒泡的BringIntoViewRequested路由事件触发的,直接拦截该事件即可禁用自动滚动行为,有两种可落地的实现方式:
方案1:自定义控件派生类(推荐,不影响手动调用滚动逻辑)
通过重写TreeViewItem的BringIntoView请求处理,禁用选中触发的默认滚动,不会影响你后续手动调用滚动接口的能力:
- 自定义TreeViewItem容器类,拦截默认的BringIntoView处理逻辑
public class DisableAutoScrollTreeViewItem : TreeViewItem { protected override void OnBringIntoViewRequested(BringIntoViewRequestedEventArgs e) { // 不执行基类逻辑,阻止默认滚动触发 e.Handled = true; } } - 自定义TreeView类,替换默认的项容器生成逻辑
public class DisableAutoScrollTreeView : TreeView { protected override DependencyObject GetContainerForItemOverride() { return new DisableAutoScrollTreeViewItem(); } protected override bool IsItemItsOwnContainerOverride(object item) { return item is DisableAutoScrollTreeViewItem; } } - 直接在XAML中替换原生TreeView为你自定义的
DisableAutoScrollTreeView即可生效。
方案2:可视化树查找ScrollViewer拦截事件(无需自定义控件)
如果不想新增自定义控件类,可以在TreeView加载完成后,找到其内部封装的ScrollViewer控件,直接在ScrollViewer层面拦截冒泡的BringIntoView请求:
- 给TreeView添加Loaded事件处理,在事件中查找内部ScrollViewer并拦截滚动请求
private void TreeView_Loaded(object sender, RoutedEventArgs e) { // 查找TreeView内部的ScrollViewer ScrollViewer treeScrollViewer = FindVisualChild<ScrollViewer>(sender as TreeView); if (treeScrollViewer != null) { treeScrollViewer.BringIntoViewRequested += (_, args) => { // 标记事件已处理,阻止自动滚动 args.Handled = true; }; } } // 可视化树子元素查找辅助方法 private T FindVisualChild<T>(DependencyObject parent) where T : DependencyObject { if (parent == null) return null; int childCount = VisualTreeHelper.GetChildrenCount(parent); for (int i = 0; i < childCount; i++) { DependencyObject child = VisualTreeHelper.GetChild(parent, i); if (child is T target) return target; T childResult = FindVisualChild<T>(child); if (childResult != null) return childResult; } return null; }
注意:该方案会拦截所有流向该ScrollViewer的BringIntoView请求,包括你手动调用
StartBringIntoView触发的滚动,如果需要保留手动滚动能力,建议使用方案1。
内容的提问来源于stack exchange,提问作者Badhan Sen
相关产品推荐
相关产品推荐

