将ListBox放在ScrollViewer中:鼠标滚轮不起作用

Rob*_*Dam 8 c# wpf xaml listbox scrollviewer

把一个当我的鼠标滚轮不起作用ListBoxScrollViewer.

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>
Run Code Online (Sandbox Code Playgroud)

编辑:按照Joel的要求,添加了我之所以这样做的原因..我这样做是因为我不喜欢ListBox内部ScrollViewer对我的布局做了什么.我有一个背景图片,除此之外,ListBox如下图所示:

替代文字http://robbertdam.nl/share/1.png

现在,当滚动条出现时,会发生以下情况:

替代文字http://robbertdam.nl/share/2.png

我创建了一个样式ScrollViewer,显示滚动条顶部的的ListBox项目内容.在ListBox项目的datatemplate中,我为滚动条保留了一些空间.

谢谢,Robbert Dam

Joe*_*ant 15

首先,我认为你需要详细说明你的局限性以及你想要实现的目标.没有它,我只能解释为什么你所做的不起作用.有人甚至可能对如何获得你想要的结果有更好的了解.

如果你把ListBox里面ScrollViewer,则控制模板ListBox还是有其自己的ScrollViewer内部.当鼠标光标位于ListBox并且您滚动鼠标滚轮时,该事件会一直冒泡,直到它到达该ScrollViewer部分ListBox.那个人通过滚动来处理它并将事件标记为已处理,因此ScrollViewer你把ListBox内部忽略了事件.

如果你做得ListBox比外面更高更窄ScrollViewer,并给它足够的物品,以便它ListBox自己可以滚动物品,你会看到2个垂直滚动条:1个在ListBox外面,1个在ListBox外面ScrollViewer.当鼠标光标位于其中时ListBox,ListBox将使用其内部滚动项目ScrollViewer,并且Border它将保持原位.当鼠标光标是外ListBox和内外侧ScrollViewer,即ScrollViewer将滚动它的内容-的ListBox-你可以通过注意到验证ListBoxBorder改变位置.

如果你想要一个外部ScrollViewer来滚动整个ListBox控件(包括Border而不仅仅是项目),你需要重新设计它ListBox以使它没有内部ScrollViewer,但你还需要确保它自动获得根据其项目更大.

出于某些原因,我不推荐这种方法.如果其中有其他控件可能是有意义ScrollViewerListBox,但是你的样本并没有表明这一点.此外,如果您将要有很多项目ListBox,那么您将为ListBoxItem每一个项目创建s,从而消除了默认的非重新ListBox设置的默认优势VirtualizingStackPanel.

请告诉我们您的实际要求.


编辑:好的,现在我有一个更好的主意,添加了这些图像.你得到的效果是,当有足够的项目滚动并且滚动条出现时,可用区域必须水平缩小一点,因为ScrollViewer模板使用了一个Grid.这些似乎是你的选择,按顺序越来越好:

  1. 重新设计ListBox没有ScrollViewer和使用你重新设计的ScrollViewer外面ListBox.然后你还必须强制它ListBox也足够高,以显示相同的每个项目Style,现在你已经失去了UI虚拟化.如果您要在列表中显示数百个项目,那么您绝对不想失去它.
  2. 重新ListBox设置样式并将其设置ControlTemplate为使用ScrollViewer已为其创建的样式,将滚动条放在内容上而不是单独的列中.这一个是好的(ListBox限制它的高度并使用a VirtualizingStackPanel,yay),但正如你所说,它需要你的意识DataTemplate.
  3. 重新设计ScrollViewer为垂直滚动条留出空间,即使它不可见.这是这个选项的样子:

默认情况下,ScrollViewer使用Grid等效于此的2列:

<Grid.ColumnDefinitions>
    <ColumnDefinition Width="*" />
    <ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
Run Code Online (Sandbox Code Playgroud)

因此,Width当滚动条不可见时,滚动条列的列为0 Width="Auto".要为滚动条留出空间,即使它被隐藏,我们也会Width将该列绑定到Width垂直滚动条:

<Grid.ColumnDefinitions>
    <ColumnDefinition Width="*" />
    <ColumnDefinition
        Width="{Binding ElementName=PART_VerticalScrollBar, Path=Width}" />
</Grid.ColumnDefinitions>
Run Code Online (Sandbox Code Playgroud)

所以现在ControlTemplate在自定义StyleScrollViewer可能看起来像这样:

<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>
Run Code Online (Sandbox Code Playgroud)

您甚至可以将内容列设置为固定大小和滚动条列Width="*",如果图像未拉伸,则可能会在长时间内更好地工作.现在,DataTemplate不必为滚动条的宽度进行补偿,因为无论滚动条是否可见,它都可以使用一致的区域.

你可能要检查出其余例子ControlTemplateScrollViewer,但这些例子并非默认样式.请注意,该示例将垂直滚动条放在左侧!另请注意底部的评论ContentScrollPresenter.


小智 7

我正在处理同一个问题。我设置了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>
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助。