[英]Listview inside of scrollviewer prevents scrollviewer scroll
我有一個帶有幾個列表框的滾動查看器。 問題是,如果用戶在鼠標懸停在列表視圖上時使用鼠標中滾輪滾動滾動查看器。 listview 將其內部 scrollviewer 滾動到底部,然后繼續捕獲鼠標,防止包含的 scrollviewer 滾動。
關於如何處理這個的任何想法?
發生這種情況是因為ListView
的(實際上是ListBox
的)內容模板自己用ScrollViewer
包裝了它的項目。
最簡單的方法是通過為內部ListView
刪除您自己的Template
來禁用它,該Template
不會創建ScrollViewer
:
<ListView>
<ListView.Template>
<ControlTemplate>
<ItemsPresenter></ItemsPresenter>
</ControlTemplate>
</ListView.Template>
...
</ListView>
順便說一句,如果您在 ListView 中有一個 ListView(這是我的情況),也會發生同樣的情況。
您是否嘗試禁用ListView's
ScrollBars
?
<ListView ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Disabled" />
IMO,處理這種情況的最佳方法是創建自定義控件:
class MyScrollViewer : ScrollViewer
{
protected override void OnPreviewMouseWheel(MouseWheelEventArgs e)
{
base.OnPreviewMouseWheel(e);
if (!e.Handled)
{
e.Handled = true;
this.RaiseEvent(new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta)
{
RoutedEvent = UIElement.MouseWheelEvent,
Source = this
});
}
}
}
受到一些有用答案的啟發,我有一個實現,當內部(包括來自 ListView、ListBox、DataGrid)滾動超過它們的頂部/底部時,滾動祖先 ScrollViewers。
我將附加屬性應用於 App.xaml 中的所有 ScrollViewers:
<Style TargetType="ScrollViewer" BasedOn="{StaticResource {x:Type ScrollViewer}}">
<Setter Property="local:ScrollViewerHelper.FixMouseWheel" Value="True" />
</Style>
附加屬性檢測滾動超過頂部/底部,當發生這種情況時,會在 ScrollViewer 的父級上引發鼠標滾輪事件。 事件路由將其發送到外部 ScrollViewer:
public static class ScrollViewerHelper
{
// Attached property boilerplate
public static bool GetFixMouseWheel(ScrollViewer scrollViewer) => (bool)scrollViewer?.GetValue(FixMouseWheelProperty);
public static void SetFixMouseWheel(ScrollViewer scrollViewer, bool value) => scrollViewer?.SetValue(FixMouseWheelProperty, value);
public static readonly DependencyProperty FixMouseWheelProperty =
DependencyProperty.RegisterAttached("FixMouseWheel", typeof(bool), typeof(ScrollViewerHelper),
new PropertyMetadata(OnFixMouseWheelChanged));
// End attached property boilerplate
static void OnFixMouseWheelChanged(DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
var scrollViewer = d as ScrollViewer;
if (scrollViewer == null) return;
scrollViewer.PreviewMouseWheel += (s2, e2) =>
{
var parent = scrollViewer.Parent as UIElement;
bool hitTopOrBottom = HitTopOrBottom(e2.Delta, scrollViewer);
if (parent is null || !hitTopOrBottom) return;
var argsCopy = Copy(e2);
parent.RaiseEvent(argsCopy);
};
}
static bool HitTopOrBottom(double delta, ScrollViewer scrollViewer)
{
var contentVerticalOffset = scrollViewer.ContentVerticalOffset;
var atTop = contentVerticalOffset == 0;
var movedUp = delta > 0;
var hitTop = atTop && movedUp;
var atBottom =
contentVerticalOffset == scrollViewer.ScrollableHeight;
var movedDown = delta < 0;
var hitBottom = atBottom && movedDown;
return hitTop || hitBottom;
}
static MouseWheelEventArgs Copy(MouseWheelEventArgs e)
=> new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta)
{
RoutedEvent = UIElement.MouseWheelEvent,
Source = e.Source,
};
}
如果將內部列表視圖包裝在滾動查看器中,則滾動將起作用。
<ListView ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListView.ItemTemplate>
<DataTemplate>
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Disabled">
<ListView>
<ListView.ItemTemplate>
<DataTemplate>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ScrollViewer>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.