71

我目前正在研究我的第一个 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 滚动仍然有效)。我是否应该以不同的方式处理项目的拖动(在想要添加滚动条之前对我来说效果很好)?或者有没有办法检测光标是否在滚动条上方(所以我可以取消选择启用滚动的项目)?或者还有其他建议吗?

4

6 回答 6

115

这可能会帮助你..

private void ListViewScrollViewer_PreviewMouseWheel(object sender, System.Windows.Input.MouseWheelEventArgs e)
{
   ScrollViewer scv = (ScrollViewer)sender;
   scv.ScrollToVerticalOffset(scv.VerticalOffset - e.Delta);
   e.Handled = true;
 }
于 2013-04-26T11:52:59.970 回答
26

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

<ListView.Template>
    <ControlTemplate>
        <ScrollViewer>
            <ItemsPresenter></ItemsPresenter> 
        </ScrollViewer>
    </ControlTemplate>
</ListView.Template>
于 2014-06-03T23:29:44.813 回答
17

对我来说,这很有效:

<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>
于 2018-06-06T08:24:16.117 回答
10
<ScrollViewer Background="Transparent">

如果Background为 null,则鼠标滚轮将不起作用ScrollViewer。您可以设置BackgroundtoTransparent或其他值。

于 2015-07-04T04:55:39.990 回答
6

就我而言,这有帮助:

<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.

于 2016-10-13T07:35:18.793 回答
1

我想对 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;
}
于 2019-06-24T11:41:21.323 回答