2009-08-18 65 views
5

ListBox放入ScrollViewer中时,我的鼠标滚轮不起作用。将列表框放入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> 

编辑:乔尔的要求,加入我为什么这样做的原因.. 我这样做是因为我不喜欢什么ListBox的内部ScrollViewer与我的布局。我有一个背景图像和上一个ListBox顶部如下图所示:现在

alt text http://robbertdam.nl/share/1.png

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

alt text http://robbertdam.nl/share/2.png

我已经创建了一个ScrollViewer的样式显示ListBox项目内容的顶部上的滚动条。在ListBox项目的数据模板中,我为滚动条保留了一些空间。

感谢, Robbert大坝

回答

15

首先,我认为你需要详细说明你的限制是什么,以及你想达到的目标。没有这个,我只能解释你为什么做不到。有人甚至可以更好地了解如何获得后续结果。

如果你把一个ListBox里面ScrollViewer,那么control templateListBox仍然有它自己的内部ScrollViewer。当鼠标光标位于ListBox上方,并且滚动鼠标滚轮时,该事件会冒泡,直至到达ListBoxScrollViewer。那个人通过滚动来处理它,并将事件标记为已处理,所以ScrollViewer你把ListBox忽略了事件。在ListBox 1和1之外:

如果使ListBox比外ScrollViewer更高和更窄,并给予足够的项目,以便ListBox本身可以滚动的物品,你会看到2垂直滚动条ListBox为您的外ScrollViewer。当鼠标光标位于ListBox内部时,ListBox将滚动其内部ScrollViewer的项目,其Border将保持原位。当鼠标光标在ListBox之外,并在外部ScrollViewer之内时,该ScrollViewer将滚动其内容 - ListBox - 您可以通过注意ListBoxBorder更改位置来验证。

如果你想要一个外ScrollViewer滚动整个ListBox控制(包括Border,而不仅仅是项目),你就需要重新风格ListBox因此它不具有内部ScrollViewer,但你”还需要确保它根据其物品自动变大。

我不建议这种方法,由于几个原因。如果ScrollViewer以及ListBox内有其他控件,但您的示例并未指出该示例,则可能有意义。此外,如果您要在ListBox中拥有大量商品,那么您将为每一个商品创建ListBoxItem s,从而消除由于默认VirtualizingStackPanel而导致的默认非重新设计ListBox的优势。

请让我们知道您的实际要求是什么。


编辑:好了,现在我有一个好一点的想法,增加这些图像。你得到的效果是,当有足够的项目滚动和滚动条出现时,可用区域必须水平缩小一点,因为ScrollViewer的模板使用Grid。这似乎是你的选择,在较小的到更好的顺序:

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

默认情况下,ScrollViewer使用2列在Grid这相当于:

<Grid.ColumnDefinitions> 
    <ColumnDefinition Width="*" /> 
    <ColumnDefinition Width="Auto" /> 
</Grid.ColumnDefinitions> 

所以滚动条的列的Width为0时滚动条是不可见的,因为Width="Auto"。为了留出空间用于滚动条,即使它是隐藏的,我们绑定该列的Width垂直滚动条的Width

<Grid.ColumnDefinitions> 
    <ColumnDefinition Width="*" /> 
    <ColumnDefinition 
     Width="{Binding ElementName=PART_VerticalScrollBar, Path=Width}" /> 
</Grid.ColumnDefinitions> 

所以现在在定制StyleScrollViewer可能是这样的ControlTemplate

<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不必为滚动条的宽度进行补偿,因为无论滚动条是否可见,它都会使用一致的区域。

您可能需要查看example ControlTemplate for ScrollViewer的其余部分,但这些示例不是默认样式。 请注意,该示例将垂直滚动条放在左侧!另请注意关于ContentScrollPresenter底部的评论。

+0

更新了我的帖子.. – 2009-08-19 07:33:56

3

我正在处理同样的问题。我设置了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> 

希望这有助于。

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(); 
     } 
    }