【问题标题】:ScrollViewer mouse wheel not scrollingScrollViewer 鼠标滚轮不滚动
【发布时间】:2013-04-20 12:21:10
【问题描述】:

我目前正在处理我的第一个 WPF 项目,并试图使 ListView 可滚动。 起初我认为这可以通过简单地限制ListView 的宽度和高度来轻松完成,从而在内容超出其空间时强制滚动条自动出现。起初这似乎很好,但由于处理了 PreviewMouseDown 事件(它允许拖动列表的项目),它在选择项目后不起作用。

第二次尝试(使用ScrollViewer

<ScrollViewer>
    <ListView ItemsSource="{Binding FileViewModels}"
              PreviewMouseDown="ListView_MouseMove"
              Height="450" Width="200"/>
</ScrollViewer>

当然,当列表的内容变得大于其最大高度时,这会导致第二个滚动条。并且选择项目后拖动栏仍然不起作用。

第三次(非常愚蠢)尝试(禁用滚动条重复)

<ScrollViewer>
    <ListView ItemsSource="{Binding FileViewModels}"
              PreviewMouseDown="ListView_MouseMove"
              Height="450" Width="200"
              ScrollViewer.VerticalScrollBarVisibility="Disabled"
              ScrollViewer.HorizontalScrollBarVisibility="Disabled"/>
</ScrollViewer>

这删除了滚动条副本并启用了通过鼠标滚轮滚动但禁用了滚动条,因此您无法通过单击并拖动它来移动。

第四次尝试ScrollViewer 的大小不变)

<ScrollViewer Height="450" Width="200">
    <ListView ItemsSource="{Binding FileViewModels}"
              PreviewMouseDown="ListView_MouseMove"/>
</ScrollViewer>

ListView 中删除了宽度/高度约束并将其移至ScrollViewer。这将启用滚动条并删除重复项。不幸的是,鼠标滚轮不再起作用(拖动滚动条可以正常工作)。

有人可以向我解释一下为什么鼠标滚轮不再起作用以及如何解决这个问题吗?

编辑 也许我应该回到我的第一个解决方案。

显然,ListView 的模板已经包含一个ScrollViewer。剩下的问题是,由于处理了PreviewMouseDown 事件(在这种情况下通过 MouseWheel 滚动仍然有效),我无法在选择项目后拖动滚动条。我是否应该以不同的方式处理项目的拖动(在想要添加滚动条之前,它对我来说效果很好)?或者有没有办法检测光标是否在滚动条上方(所以我可以取消选择启用滚动的项目)? 或者有其他建议吗?

【问题讨论】:

    标签: c# wpf xaml scrollviewer mousewheel


    【解决方案1】:

    这可能对你有帮助..

    private void ListViewScrollViewer_PreviewMouseWheel(object sender, System.Windows.Input.MouseWheelEventArgs e)
    {
       ScrollViewer scv = (ScrollViewer)sender;
       scv.ScrollToVerticalOffset(scv.VerticalOffset - e.Delta);
       e.Handled = true;
     }
    

    【讨论】:

    • 很好,这行得通 - 谢谢。但我仍然不确定,在 ScrollViewer 中使用 ListView 是否是好的样式(参见上面的编辑部分)。
    • 我发现将e.Delta 除以 10 可以使滚动的粒度更细(不那么粗)。 (不过答案很好!)
    【解决方案2】:

    这可能是最舒服的解决方案:

    <ListView.Template>
        <ControlTemplate>
            <ScrollViewer>
                <ItemsPresenter></ItemsPresenter> 
            </ScrollViewer>
        </ControlTemplate>
    </ListView.Template>
    

    【讨论】:

    • 最佳解决方案。可能还可以将 Itemspresenter 放入 GridDockPanel
    • 我的解决方案遇到了一个小问题。标题现在消失了。有什么建议吗?
    • @ShalvinAbraham 什么标题? Listview 没有我知道的标题?
    • 我是 WPF 新手,所以可能是我的误解.. 我使用 ListView 作为: with headers.
    • 我能够通过将
    【解决方案3】:

    对我来说这很有效:

    <ListView.Template>
        <ControlTemplate>
            <!-- Empty template to allow ScrollViewer to capture mouse scroll -->
            <ItemsPresenter />
        </ControlTemplate>
    </ListView.Template>
    

    而不是这个:

    <ListView.Template>
        <ControlTemplate>
            <ScrollViewer>
                <ItemsPresenter></ItemsPresenter>
            </ScrollViewer>
        </ControlTemplate>
    </ListView.Template>
    

    【讨论】:

      【解决方案4】:
      <ScrollViewer Background="Transparent">
      

      如果Background 为空,鼠标滚轮将无法在ScrollViewer 上工作。您可以将Background 设置为Transparent 或其他值。

      【讨论】:

      • 这仅适用于我,如果鼠标指针位于滚动条上方,但如果它位于内容上方则无效
      【解决方案5】:

      就我而言,这有帮助:

      <ScrollViewer ScrollViewer.CanContentScroll="True" ScrollViewer.VerticalScrollBarVisibility="Disabled" ScrollViewer.HorizontalScrollBarVisibility="Auto" >
          <DataGrid x:Name="dataGrid" SelectionMode="Single" ItemsSource="{Binding}"  SelectedValuePath="{Binding Item}" AutoGenerateColumns="True">
          </DataGrid>
      </ScrollViewer>
      

      设计禁用了外部范围内的VerticalScrollBarVisibility 属性,即ScrollViewer

      【讨论】:

      • 这应该是公认的答案。它工作简单。谢谢!
      • 同意。这是唯一对我有用的答案!谢谢!
      【解决方案6】:

      我想对 Rocky 提供的解决方案添加一些评论。它对我来说很好,但后来我需要在不同的窗口中使用它来滚动Grid。我遇到了一个问题:ScrollViewer 没有滚动到底端。原因是试图设置无效的VerticalOffset 值。下面的代码对我来说很好用(只需要更改 PreviewMouseWheel 处理程序:

      private void UIElement_OnPreviewMouseWheel(object sender, MouseWheelEventArgs e)
      {
          ScrollViewer scroll = (ScrollViewer)sender;
          if (e.Delta < 0)
          {
              if (scroll.VerticalOffset - e.Delta <= scroll.ExtentHeight - scroll.ViewportHeight)
              {
                  scroll.ScrollToVerticalOffset(scroll.VerticalOffset - e.Delta);
              }
              else
              {
                  scroll.ScrollToBottom();
              }
          }
          else
          {
              if (scroll.VerticalOffset + e.Delta > 0)
              {
                  scroll.ScrollToVerticalOffset(scroll.VerticalOffset - e.Delta);
              }
              else
              {
                  scroll.ScrollToTop();
              }
          }
          e.Handled = true;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-03-18
        • 1970-01-01
        • 1970-01-01
        • 2012-12-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多