TabControl中的ListBox滚动问题
我在 TabControl 中遇到 WPF ListBox 问题。当我更改选项卡时,ListBox 将其滚动条位置重置为 0。这是重现代码:
<TabControl x:Name="_tabs">
<TabItem Header="1">
<ListBox ItemsSource="{Binding}" ScrollViewer.VerticalScrollBarVisibility="Auto"/>
</TabItem>
<TabItem Header="2">
<ListBox ItemsSource="{Binding}" ScrollViewer.VerticalScrollBarVisibility="Auto"/>
</TabItem>
</TabControl>
_tabs.DataContext = Enumerable.Range(1, 300).ToArray();
当窗口打开时,我打开第二个选项卡,将列表滚动到中间某处,返回到第一个选项卡,然后再次打开第二个选项卡。由于某种原因,列表滚动到顶部。
为什么会出现这种情况?我犯了一些愚蠢的错误吗?
I have an issue with WPF ListBox in TabControl. ListBox resets it's scrollbar position to 0 when I change tabs. Here is repro code:
<TabControl x:Name="_tabs">
<TabItem Header="1">
<ListBox ItemsSource="{Binding}" ScrollViewer.VerticalScrollBarVisibility="Auto"/>
</TabItem>
<TabItem Header="2">
<ListBox ItemsSource="{Binding}" ScrollViewer.VerticalScrollBarVisibility="Auto"/>
</TabItem>
</TabControl>
_tabs.DataContext = Enumerable.Range(1, 300).ToArray();
When the window opens I open the second tab, scroll list somewhere to the middle, return to the first tab and then open the second again. For some reason the list is scrolled to the top.
Why this happens? Have I made some stupid mistake?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
WPF 的默认行为是卸载不可见的项,其中包括卸载不可见的 TabItem。这意味着当您返回选项卡时,TabItem 将重新加载,并且任何未绑定的内容(例如滚动位置)将被重置。
曾经是一个很好的网站这里 其中包含扩展 TabControl 并阻止其在切换选项卡时破坏其 TabItems 的代码,但是该网站似乎已关闭 atm。这是我使用的代码。它最初来自该网站,尽管我对其进行了一些更改。它在切换选项卡时保留 TabItems 的
ContentPresenter
,并在返回页面时使用它来重绘 TabItem。它占用了更多的内存,但我发现它的性能更好,因为 TabItem 不再需要重新创建其上的所有控件。我通常使用的 TabControl 模板如下所示:
The default behavior of WPF is to unload items which are not visible, which includes unloading TabItems which are not visible. This means when you go back to the tab, the TabItem gets re-loaded, and anything not bound (such as a scroll position) will get reset.
There
wasis a good site here which contains code to extend the TabControl and stop it from destroying it's TabItems when switching tabs, however the site appears to be down atm.Here's the code I use. It initially was from that site, although I've made some changes to it. It preserves the
ContentPresenter
of TabItems when switching tabs, and uses it to redraw the TabItem when you go back to the page. It takes up a bit more memory, however I find it better on performance since the TabItem no longer has to re-create all the controls that were on it.The TabControl template I usually use looks something like this:
很好的答案!雷切尔干杯!我无法对现有帖子发表评论,因此添加了我自己的答案。
我发现上述设法解决了问题。但是,我还发现有必要添加:
为了正确加载初始选定的选项卡 - ItemContainerGenerator 没有内容,因此 GetSelectedTabItem 无法返回 TabItem。据推测,这与应用模板时尚未发生的渲染有关。
我发现这个问题仅在绑定选项卡控件的 ItemsSource 和 SelectedItem 时才会出现 - 在我正在开发的应用程序中,我们最近已切换到使用此选项,以便我们可以以编程方式切换选项卡以执行一些自定义导航。
选项卡项内容最初是手动指定的,例如:
通过该设置,更改所选项目很好(不会在选择时重新加载选项卡),尽管它仅由 wpf 完成。这似乎表明可以在默认控件中关闭此行为,但仅当不绑定到项目列表时(尽管我没有确认是这种情况)。
我尝试的另一个解决方案是将 ItemSource 绑定模式更改为 OneTime,但这并没有解决问题(无论如何,我们在这里都没有使用 INotifyCollectionChanged 集合)。
Great answer! Cheers Rachel! I can't comment on existing posts so have added my own answer.
I found the above managed to solve the problem. However I also found it necessary to add:
to get the initial selected tab to load correctly - the ItemContainerGenerator had no contents and so GetSelectedTabItem failed to return a TabItem. Presumably this is something to do with rendering which has yet to happen when the template is applied.
I found this problem manifested itself only when binding the ItemsSource and SelectedItem of a tab control - in an application I am working on we have recently switched to using this so we could programmatically switch tabs to do a bit of custom navigation.
The Tab Item contents were originally specified by hand eg:
With that setup changing the selected item was fine (didn't reload tabs on selection) although it was only ever done by wpf. This seems to suggest that this behaviour can be turned off in the default control but only when not binding to a list of items (although I didn't confirm this to be the case).
Another solutions I attempted were changing the ItemSource binding Mode to OneTime but this did not solve the problem (we aren't using an INotifyCollectionChanged collection here anyway).