如何阻止包含ContentControl的TabControl自动向下滚动?
如何阻止包含ContentControl的TabControl自动向下滚动?
哈哈,这个问题我之前也踩过坑!其实根源是WPF的焦点自动滚动机制在搞鬼:当你切换到新的TabItem时,系统会自动把焦点转移到Tab内第一个可获得焦点的控件上(这里就是ContentControl),而ScrollViewer的默认行为就是把获得焦点的元素滚动到可视区域里。Tab2没问题是因为内容不够长,就算ContentControl获焦也不需要滚动;但Tab3里内容足够长,一触发焦点转移,ScrollViewer就自动滚下去了。
给你几个实用的解决办法,按需选就行:
方法一:让ContentControl不抢焦点
最简单省心的办法,直接给ContentControl设置Focusable="False",这样切换Tab时它不会自动获得焦点,ScrollViewer自然就不会乱滚动了:
<ContentControl Focusable="False" />
方法二:把焦点锁定在TabItem上
如果需要ContentControl保持可聚焦的能力,那可以在TabItem加载时,手动把焦点设置到TabItem本身,不让内部控件抢焦点:
先给目标TabItem加上Loaded事件:
<TabItem Header="3" Loaded="TabItem_Loaded"> <StackPanel> <TextBlock Height="1000"/> <ContentControl /> </StackPanel> </TabItem>
然后在后台代码里处理:
private void TabItem_Loaded(object sender, RoutedEventArgs e) { if (sender is TabItem tabItem) { tabItem.Focus(); } }
方法三:全局拦截ScrollViewer的自动滚动请求
如果想彻底禁止这个ScrollViewer的自动滚动行为(注意这会影响该ScrollViewer下的所有场景),可以给ScrollViewer绑定RequestBringIntoView事件,然后取消滚动请求:
<ScrollViewer RequestBringIntoView="ScrollViewer_RequestBringIntoView"> <!-- 你的页面内容 --> </ScrollViewer>
后台代码:
private void ScrollViewer_RequestBringIntoView(object sender, RequestBringIntoViewEventArgs e) { e.Handled = true; // 阻止自动滚动请求 }
亲测这几个方法都能解决你遇到的问题,优先推荐方法一,成本最低!
备注:内容来源于stack exchange,提问作者Flo




