问题描述
将 ListBox
放入 ScrollViewer
时,我的鼠标滚轮不起作用.
My mouse wheel does not work when putting a ListBox
in a ScrollViewer
.
ListBox
是否以某种方式窃取"了这个事件?
Does the ListBox
somehow "steal" this event?
<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>
应乔尔的要求,添加了我这样做的原因..我这样做是因为我不喜欢 ListBox
的内部 ScrollViewer
对我的布局所做的事情.我有一个背景图像,在其之上还有一个 ListBox
,如下所示:
as requested by Joel, added the reason why I did this..
I did this because I don't like what the ListBox
's internal ScrollViewer
does with my layout. I have a background image, and on top of that a ListBox
as shown here:
替代文字 http://robbertdam.nl/share/1.png
现在当滚动条出现时,会发生以下情况:
Now when the scrollbar appears, the following happens:
替代文字 http://robbertdam.nl/share/2.png
我为 ScrollViewer
创建了一个样式,它在 ListBox
项的内容的顶部显示滚动条.在 ListBox
项目的数据模板中,我为滚动条保留了一些空间.
I've created a Style for a ScrollViewer
that shows the scroll bar on top of the ListBox
item's content. In the ListBox
item's datatemplate I've reserved some space for the scrollbar to appear.
谢谢,罗伯特水坝
推荐答案
首先,我认为您需要详细说明您的限制是什么以及您想要实现的目标.没有那个,我只能解释为什么你正在做的事情不起作用.有人甚至可能对如何获得您所追求的结果有更好的想法.
Firstly, I think you need to elaborate on what your limitations are and what you're trying to achieve. Without that, I can only explain why what you're doing isn't working. Somebody may even have a better idea about how to get the result you're after.
如果您将 ListBox
放在 ScrollViewer
中,那么 ListBox 的 aspx" rel="noreferrer">控件模板 内部仍然有自己的 ScrollViewer
.当鼠标光标在 ListBox
上并滚动鼠标滚轮时,该事件会冒泡,直到它到达 ScrollViewer
,它是 ListBox
的一部分.那一个通过滚动来处理它并将事件标记为已处理,因此您将 ListBox
放在其中的 ScrollViewer
会忽略该事件.
If you put ListBox
inside a ScrollViewer
, then the control template for ListBox
still has its own ScrollViewer
inside. When the mouse cursor is over the ListBox
and you scroll the mousewheel, that event bubbles up until it reaches the ScrollViewer
that's part of ListBox
. That one handles it by scrolling and marks the event as handled, so then the ScrollViewer
you put the ListBox
inside of ignores the event.
如果你让 ListBox
比外面的 ScrollViewer
更高和更窄,并给它足够的项目,以便 ListBox
本身可以滚动项目,您将看到 2 个垂直滚动条:1 个位于 ListBox
中,1 个位于 ListBox
外部,用于您的外部 ScrollViewer
.当鼠标光标在 ListBox
内时,ListBox
将使用其内部 ScrollViewer
及其 Border
滚动项目> 将留在原地.当鼠标光标在 ListBox
之外并且在外部 ScrollViewer
内时,该 ScrollViewer
将滚动其内容 -- ListBox
-- 您可以通过注意 ListBox
的 Border
更改位置来验证.
If you make the ListBox
taller and narrower than the outer ScrollViewer
, and give it enough items so that the ListBox
itself can scroll the items, you'll see 2 vertical scroll bars: 1 in the ListBox
, and 1 outside the ListBox
for your outer ScrollViewer
. When the mouse cursor is inside the ListBox
, the ListBox
will scroll the items with its internal ScrollViewer
, and its Border
will stay in place. When the mouse cursor is outside the ListBox
and inside the outer ScrollViewer
, that ScrollViewer
will scroll its contents -- the ListBox
-- which you can verify by noting that the ListBox
's Border
changes position.
如果您希望外部 ScrollViewer
滚动整个 ListBox
控件(包括 Border
而不仅仅是项目),您将需要重新设置 ListBox
的样式,使其没有内部 ScrollViewer
,但您还需要确保它根据项目自动变大.
If you want an outer ScrollViewer
to scroll the entire ListBox
control (including the Border
and not just the items), you'll need to re-style the ListBox
so that it does not have an internal ScrollViewer
, but you'll also need to make sure it automatically gets bigger according to its items.
出于几个原因,我不推荐这种方法.如果 ScrollViewer
和 ListBox
内还有其他控件可能有意义,但您的示例并未表明这一点.此外,如果您要在 ListBox
中有很多项目,您将为每个项目创建 ListBoxItem
,从而消除默认设置的任何优势,由于默认的 VirtualizingStackPanel
,非重新样式的 ListBox
为您提供.
I don't recommend this approach for a couple reasons. It might make sense if there are other controls inside the ScrollViewer
along with the ListBox
, but your sample does not indicate that. Also, if you're going to have a lot of items in the ListBox
, you'll be creating ListBoxItem
s for every single one, eliminating any advantage that the default, non-re-styled ListBox
gives you due to the default VirtualizingStackPanel
.
请告诉我们您的实际要求.
Please let us know what your actual requirements are.
好的,现在我有了更好的主意,添加了这些图像.你得到的效果是当有足够的项目滚动并且出现滚动条时,可用区域必须水平缩小一点,因为 ScrollViewer
的模板使用 Grid代码>.这些似乎是您的选择,按从小到大的顺序排列:
Ok, now I have a little better idea, with the addition of those images. The effect you're getting is that when there are enough items to scroll and the scrollbar appears, the available area has to shrink a bit horizontally because the ScrollViewer
's template uses a Grid
. These seem to be your options, in order of lesser-to-better:
- 重新设置
ListBox
的样式,使其没有ScrollViewer
并在ListBox
ScrollViewer>.然后,您还必须强制ListBox
也足够高以显示同一Style
中的每个项目,现在您已经失去了 UI 虚拟化.如果您要在列表中显示数百个项目,那么您肯定不想丢失它. - 重新设置
ListBox
的样式并将ControlTemplate
设置为使用ScrollViewer
并使用您已经为其创建的样式来放置滚动条内容而不是在单独的列中.这个没问题(ListBox
可以限制其高度并使用VirtualizingStackPanel
,是的),但正如您所说,它需要在您的DataTemplate代码>.
- 重新设置
ScrollViewer
的样式,以便为垂直滚动条留出空间,即使它不可见.此选项如下所示:
- Re-style the
ListBox
to not have aScrollViewer
and use your re-styledScrollViewer
outside theListBox
. You'd then also have to force theListBox
to also be tall enough to show every item in that sameStyle
, and now you've lost UI virtualization. If you're going to be showing hundreds of items in the list, you definitely don't want to lose that. - Re-style the
ListBox
and set theControlTemplate
to use aScrollViewer
with the style you already created for it that puts the scrollbar over the content rather than in a separate column. This one's ok (ListBox
gets to limit its height and use aVirtualizingStackPanel
, yay), but as you said, it necessitates awareness of that in yourDataTemplate
. - Re-style the
ScrollViewer
to leave space for vertical scrollbar even when it is not visible. Here's what this option looks like:
默认情况下,ScrollViewer
在 Grid
中使用 2 列,相当于:
By default, ScrollViewer
uses 2 columns in a Grid
equivalent to this:
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
因此,当滚动条自Width="Auto"
以来不可见时,滚动条列的Width
为0.为了在滚动条隐藏时也为滚动条留出空间,我们将该列的 Width
绑定到垂直滚动条的 Width
:
So the Width
of the scrollbar's column is 0 when the scrollbar is not visible since Width="Auto"
. To leave space for the scrollbar even when it is hidden, we bind the Width
of that column to the Width
of the vertical scroll bar:
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition
Width="{Binding ElementName=PART_VerticalScrollBar, Path=Width}" />
</Grid.ColumnDefinitions>
所以现在 ScrollViewer
的自定义 Style
中的 ControlTemplate
可能如下所示:
So now the ControlTemplate
in the custom Style
for ScrollViewer
might look like this:
<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>
您甚至可以将内容列设置为固定大小,并将滚动条列设置为 Width="*"
,如果您的图像没有被拉伸,从长远来看,这可能会更好.现在 DataTemplate
不必补偿滚动条的宽度,因为它获得了一致的区域来使用滚动条是否可见.
You could even make the content column a fixed size and the scrollbar column Width="*"
, which might work better in the long run if your image is not stretched. Now the DataTemplate
does not have to compenstate for the width of a scrollbar, as it gets a consistent area to use whether the scrollbar is visible or not.
您可能需要查看 示例 的其余部分
,但这些示例不是默认样式.请注意,该示例将垂直滚动条放在左侧!还要注意底部关于 ScrollViewer
的 ControlTemplateContentScrollPresenter
的注释.
You'll probably want to check out the rest of the example ControlTemplate
for ScrollViewer
, but those examples are not the default styles. Note that the example puts the vertical scrollbar on the left! Also note the comment at the bottom about ContentScrollPresenter
.
这篇关于将 ListBox 放入 ScrollViewer:鼠标滚轮不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!