11

将 aListBox放入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's internalScrollViewer对我的布局所做的事情。我有一个背景图片,最重要的是,ListBox如下所示:

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

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

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

我为 a 创建了一个 Style,它在项目内容的顶部ScrollViewer显示滚动条。在项目的数据模板中,我为滚动条保留了一些空间。ListBoxListBox

谢谢,罗伯特·达姆

4

4 回答 4

16

首先,我认为您需要详细说明您的限制是什么以及您要达到的目标。没有那个,我只能解释为什么你正在做的事情不起作用。有人甚至可能对如何获得您所追求的结果有更好的想法。

如果你放在ListBox一个里面ScrollViewer,那么控件模板ListBox仍然有它自己的里面ScrollViewer。当鼠标光标在 上并且您滚动鼠标滚轮时,该事件会冒泡,ListBox直到到达ScrollViewer. ListBox那一个通过滚动来处理它并将事件标记为已处理,所以ScrollViewer你把它放在ListBox里面会忽略该事件。

如果您使 theListBox比 outer 更高更窄ScrollViewer,并为其提供足够的项目以使其ListBox本身可以滚动项目,您将看到 2 个垂直滚动条: 1 个在 theListBox中,1 个在 the 外部ListBox用于您的 outer ScrollViewer。当鼠标光标位于 内部时ListBoxListBox将使用其内部滚动项目ScrollViewer,并且Border将保持在原位。当鼠标光标在外部ListBox和外部ScrollViewer时,ScrollViewer将滚动其内容 -ListBox您可以通过注意ListBox'Border更改位置来验证。

如果您希望外部ScrollViewer滚动整个ListBox控件(包括Border而不仅仅是项目),您需要重新设置样式以ListBox使其没有内部ScrollViewer,但您还需要确保它自动获取根据其项目更大。

我不推荐这种方法有几个原因。ScrollViewer如果 内部还有其他控件可能有意义ListBox,但您的示例并未表明这一点。此外,如果您要在 中拥有很多项目ListBox,您将为ListBoxItem每一个项目创建 s,从而消除默认的、非重新样式化的ListBox由于默认而给您带来的任何优势VirtualizingStackPanel

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


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

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

默认情况下,使用与此等效的ScrollViewer2 列: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>

所以现在ControlTemplate自定义中的StyleforScrollViewer可能如下所示:

<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不必补偿滚动条的宽度,因为它获得了一致的区域来使用滚动条是否可见。

您可能想查看示例ControlTemplateScrollViewer其余部分,但这些示例不是默认样式。请注意,该示例将垂直滚动条放在左侧!另请注意底部关于ContentScrollPresenter.

于 2009-08-18T15:52:37.457 回答
9

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

希望这可以帮助。

于 2014-07-30T15:09:25.610 回答
0

请参阅此链接以获取另一个答案:当鼠标悬停在 ListBox 上时在 ScrollViewer 中滚动

您好,我认为您可以处理整个 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();
        }
    }
于 2017-05-12T18:36:27.470 回答
0

如果您只是想让鼠标滚动而不需要 ScrollViewer 的样式:

  • 移除外部的 ScrollViewer。
  • 使用 ListBox 内的 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>
于 2021-02-11T14:03:46.960 回答