鼠标滚轮未滚动

我目前正在做我的第一个 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 滚动仍然工作在这种情况下)。我是否应该以不同的方式处理拖动项目(在添加滚动条之前,它对我来说工作得很好) ?或者有没有办法检测光标是否在滚动条上方(这样我就可以取消选择启用滚动的项目) ? 还有其他建议吗?

54031 次浏览

这个也许能帮到你。

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

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

<ListView.Template>
<ControlTemplate>
<ScrollViewer>
<ItemsPresenter></ItemsPresenter>
</ScrollViewer>
</ControlTemplate>
</ListView.Template>
<ScrollViewer Background="Transparent">

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

对我而言,这有所帮助:

<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中。

对我来说,这个方法奏效了:

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

我想对 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;
}