我在TabControl中遇到了WPF ListBox的问题 . 当我更改标签时,ListBox将其滚动条位置重置为0 . 这是repro代码:
<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();
当窗口打开时,我打开第二个选项卡,将列表滚动到中间位置,返回到第一个选项卡,然后再次打开第二个选项卡 . 由于某种原因,列表滚动到顶部 .
为什么会这样?我犯了一些愚蠢的错误吗?
2 回答
WPF的默认行为是卸载不可见的项目,包括卸载不可见的TabItems . 这意味着当您返回选项卡时,TabItem将被重新加载,并且任何未绑定的内容(例如滚动位置)都将被重置 .
有一个很好的网站here,其中包含扩展TabControl的代码,并在切换标签时阻止它破坏它的TabItems,但是该网站似乎已经关闭了atm .
这里's the code I use. It initially was from that site, although I' ve对它做了一些修改 . 它在切换选项卡时会保留
ContentPresenter
的TabItems,并在您返回页面时使用它重绘TabItem . 它占用了更多的内存,但我发现它在性能上更好,因为TabItem不再需要重新创建它上面的所有控件 .我经常使用的TabControl模板看起来像这样:
很棒的答案!干杯雷切尔!我无法评论现有帖子,所以添加了我自己的答案 .
我发现以上设法解决了这个问题 . 但是我也发现有必要添加:
获取正确加载的初始选定选项卡 - ItemContainerGenerator没有内容,因此GetSelectedTabItem无法返回TabItem . 据推测,这与应用模板时尚未发生的渲染有关 .
我发现只有在绑定选项卡控件的ItemsSource和SelectedItem时才会出现这个问题 - 在我正在处理的应用程序中,我们最近切换到使用它,所以我们可以通过编程方式切换选项卡来进行一些自定义导航 .
Tab Item内容最初是手工指定的,例如:
使用该设置更改所选项目很好(没有重新加载选项上的选项卡)虽然它只是由wpf完成 . 这似乎表明可以在默认控件中关闭此行为,但仅在未绑定到项目列表时才会关闭(尽管我没有确认是这种情况) .
我尝试的另一个解决方案是将ItemSource绑定模式更改为OneTime,但这并没有解决问题(我们此处未使用INotifyCollectionChanged集合) .