我有带ScrollViewer的ListBox
<ScrollViewer Focusable="False" CanContentScroll="True"
HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Disabled">
<ListBox ItemsSource="{Binding Path=MyItems}" VerticalAlignment="Stretch" Focusable="False">
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border CornerRadius="3,3,3,3">
<Grid>
<myControls:MyControl/>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.Style>
<Style TargetType="ListBox">
<Setter Property="SnapsToDevicePixels" Value="true"/>
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="ScrollViewer.CanContentScroll" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBox">
<ScrollViewer Focusable="False" CanContentScroll="True">
<Border>
<StackPanel Margin="2" Orientation="Horizontal" IsItemsHost="True"/>
</Border>
</ScrollViewer>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.Style>
</ListBox>
</ScrollViewer>
但CanContentScroll =“True”不起作用。它仍然以物理单位滚动。 我的代码有什么问题?谢谢!
答案 0 :(得分:3)
问题是ScrollViewer和StackPanel之间的边界,这阻止了ScrollViewer找到StackPanel。 StackPanel实现了IScrollInfo接口以进行逻辑滚动,但是如果ScrollViewer找不到IScrollInfo子节点,则它会回退到物理滚动。
有三种方法可以在ScrollViewer中获取逻辑滚动:
简单的解决方案
前两个解决方案是不言自明的,但我想指出,使用ItemsPresenter可能比直接在模板中包含StackPanel更好。这样,解决方案中的其他ListBox可以利用ControlTemplate而不必强制使用相同的面板。换句话说,我会做这样的事情而不是你写的:
<ListBox>
<ListBox.ItemContainerStyle>
...
</ListBox.ItemContainerStyle>
<ListBox.ItemsPanel>
<ItemContainerTemplate>
<StackPanel Margin="2" Orientation="Horizontal" ... />
</ItemContainerTemplate>
</ListBox.ItemsPanel>
<ListBox.Template>
<ControlTemplate>
<ScrollViewer Focusable="False" CanContentScroll="True">
<ItemsPresenter />
</ScrollViewer>
</ControlTemplate>
</ListBox.Template>
</ListBox>
高级技术
如果确实需要在逻辑滚动的StackPanel周围显示边框但是该边框似乎随数据滚动,则必须进行一些额外的管道。当StackPanel进行逻辑滚动时,StackPanel本身会在排列过程中滚动其内容,而ScrollViewer根本不会进行任何实际滚动(它只管理滚动条等)。你会发现StackPanel坚决拒绝滚动任何实际上并不是它的子项之一的东西,所以除非你的边框可以是一个真正的ListBox项,否则你需要做一些假装。
使其看起来像StackPanel内容一样滚动:
检测StackPanel的滚动状态可以通过在0和Items.Count-1上调用ItemContainerGenerator.ContainerFromIndex,然后在StackPanel中检查这些容器的位置来查看它们是否可见。如果是这样,边框的顶部和底部(或左侧和右侧的Orientation = Horizontal)应该是可见的,否则它们不应该是可见的。当然,其他方面总是可见的。