将ListBox
放入ScrollViewer
时,我的鼠标滚轮无效。
ListBox
以某种方式“窃取”此事件吗?
<ScrollViewer VerticalScrollBarVisibility="Auto" Style="{StaticResource myStyle}">
<ListBox>
<ListBoxItem>Test 1</ListBoxItem>
<ListBoxItem>Test 2</ListBoxItem>
<ListBoxItem>Test 3</ListBoxItem>
<ListBoxItem>Test 4</ListBoxItem>
<ListBoxItem>Test 5</ListBoxItem>
<ListBoxItem>Test 6</ListBoxItem>
<ListBoxItem>Test 7</ListBoxItem>
</ListBox>
</ScrollViewer>
编辑:按照Joel的要求,添加了我这样做的原因..
我这样做是因为我不喜欢ListBox
的内部ScrollViewer
对我的布局所做的事情。我有一张背景图片,最重要的是ListBox
,如下所示:
alt text http://robbertdam.nl/share/1.png
现在当滚动条出现时,会发生以下情况:
alt text http://robbertdam.nl/share/2.png
我为ScrollViewer
创建了一个样式,用于显示ListBox
项内容的顶部上的滚动条。在ListBox
项的datatemplate中,我为滚动条保留了一些空间。
谢谢, 罗伯特大坝
答案 0 :(得分:15)
首先,我认为您需要详细说明您的限制是什么以及您想要实现的目标。没有它,我只能解释为什么你所做的不起作用。有些人甚至可能对如何获得你想要的结果有更好的了解。
如果您将ListBox
放在ScrollViewer
内,那么ListBox
的{{3}}内部仍然有自己的ScrollViewer
。当鼠标光标位于ListBox
上方并滚动鼠标滚轮时,该事件会一直冒泡,直到它到达ScrollViewer
ListBox
的一部分。那个人通过滚动处理它并将事件标记为已处理,因此ScrollViewer
放入ListBox
忽略事件。
如果你使ListBox
比外ScrollViewer
更高更窄,并给它足够的项目,以便ListBox
本身可以滚动项目,你会看到2垂直滚动条形:ListBox
中有1条,外部ListBox
位于ScrollViewer
外1条。当鼠标光标位于ListBox
内时,ListBox
将使用其内部ScrollViewer
滚动项目,其Border
将保留在原位。当鼠标光标位于ListBox
之外且位于外部ScrollViewer
之内时,ScrollViewer
将滚动其内容 - ListBox
- 您可以通过注意到它来验证ListBox
的{{1}}改变了位置。
如果您希望外部Border
滚动整个ScrollViewer
控件(包括ListBox
而不仅仅是项目),则需要重新设置{{1所以它没有内部Border
,但你还需要确保它根据其项目自动变大。
出于某些原因,我不推荐这种方法。如果ListBox
内有其他控件和ScrollViewer
,则可能有意义,但您的示例并未表明这一点。此外,如果您要在ScrollViewer
中添加大量项目,则会为每个项目创建ListBox
个,从而消除了默认的非重新设置{ {1}}由于默认ListBox
而为您提供。
请告诉我们您的实际要求。
编辑:好的,现在我有了更好的想法,添加了这些图片。您获得的效果是,当有足够的项目滚动并且滚动条出现时,可用区域必须水平缩小一点,因为ListBoxItem
的模板使用ListBox
。这些似乎是你的选择,按照从小到好的顺序:
VirtualizingStackPanel
重新设置为没有ScrollViewer
,并在Grid
之外使用重新设置的ListBox
。然后,您还必须强制ScrollViewer
也足够高,以显示同一ScrollViewer
中的每个项目,现在您已经失去了UI虚拟化。如果您要在列表中显示数百个项目,那么肯定不想丢失它。ListBox
样式,并将ListBox
设置为使用您已为其创建的样式的Style
,将滚动条放在内容上而不是单独的列中。这一个没问题(ListBox
限制其高度并使用ControlTemplate
,yay),但正如您所说,它需要在ScrollViewer
中意识到这一点。ListBox
样式,为垂直滚动条留出空间,即使它不可见。以下是此选项的含义:默认情况下,VirtualizingStackPanel
使用与DataTemplate
等效的2列:
ScrollViewer
因此,当ScrollViewer
后滚动条不可见时,滚动条列的Grid
为0。要为滚动条留出空间,即使它已被隐藏,我们也会将该列的<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
绑定到垂直滚动条的Width
:
Width="Auto"
现在,Width
的自定义Width
中的<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition
Width="{Binding ElementName=PART_VerticalScrollBar, Path=Width}" />
</Grid.ColumnDefinitions>
可能如下所示:
ControlTemplate
您甚至可以将内容列设置为固定大小和滚动条列Style
,如果图像未拉伸,则可能会在长时间内更好地工作。现在ScrollViewer
不必为滚动条的宽度进行补偿,因为无论滚动条是否可见,它都可以使用一致的区域。
您可能希望查看control template的其余部分,但这些示例不是默认样式。 请注意,该示例将垂直滚动条放在左侧!另请注意底部有关<ControlTemplate
TargetType="{x:Type ScrollViewer}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition
Width="{Binding ElementName=PART_VerticalScrollBar, Path=Width}" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition
Height="Auto" />
</Grid.RowDefinitions>
<ScrollContentPresenter />
<ScrollBar
Grid.Column="1"
Name="PART_VerticalScrollBar"
Value="{TemplateBinding VerticalOffset}"
Maximum="{TemplateBinding ScrollableHeight}"
ViewportSize="{TemplateBinding ViewportHeight}"
Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" />
<ScrollBar
Name="PART_HorizontalScrollBar"
Orientation="Horizontal"
Grid.Row="1"
Value="{TemplateBinding HorizontalOffset}"
Maximum="{TemplateBinding ScrollableWidth}"
ViewportSize="{TemplateBinding ViewportWidth}"
Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" />
</Grid>
</ControlTemplate>
。
答案 1 :(得分:5)
我正在处理同样的问题。我设置了 ListBox.ItemsPanel 属性,没有任何 ScrollViewer :
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">
<ListBox>
<ListBox.Template>
<ControlTemplate TargetType="ItemsControl">
<Border>
<ItemsPresenter />
</Border>
</ControlTemplate>
</ListBox.Template>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<\ListBox>
<\ScrollViewer>
希望这有帮助。
答案 2 :(得分:0)
请参阅此链接以获取其他答案:Scroll in ScrollViewer when mouse over ListBox
您好,我认为您可以处理整个ListBox的PreviewMouseWheel事件。只要您不处理每个项目的
,这也会影响单个项目PreviewMouseWheel and mark the event as handled:
private void ListBox_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
if (e.Delta < 0)
{
scrollViewer1.LineDown();
}
else
{
scrollViewer1.LineUp();
}
}
答案 3 :(得分:0)
如果您只想使鼠标滚动而无需为 ScrollViewer 设置样式:
请参阅此示例的前两行:
<ListBox ScrollViewer.VerticalScrollBarVisibility="Auto"
ScrollViewer.HorizontalScrollBarVisibility="Auto">
<ListBoxItem>Test 1</ListBoxItem>
<ListBoxItem>Test 2</ListBoxItem>
<ListBoxItem>Test 3</ListBoxItem>
<ListBoxItem>Test 4</ListBoxItem>
<ListBoxItem>Test 5</ListBoxItem>
<ListBoxItem>Test 6</ListBoxItem>
<ListBoxItem>Test 7</ListBoxItem>
</ListBox>