WPF ItemsControl 控件支持鼠标滚轮滑动
此文章意在解决在WPF中ItemsControl类型的集合控件支持鼠标滚轮操作,并可控制滚动的速度。
第一步:给ItemsControl添加滚轮事件。
this.listBox.AddHandler(ListBox.MouseWheelEvent, new MouseWheelEventHandler(list_MouseWheel), true);
第二步:实现list_MouseWheel处理函数。
private void list_MouseWheel(object sender, MouseWheelEventArgs e)
{
ItemsControl items = (ItemsControl)sender;
ScrollViewer scroll = FindVisualChild<ScrollViewer>(items);
scroll.PanningMode = PanningMode.HorizontalOnly;
if (scroll != null)
{
int d = e.Delta;
if (d > 0)
{
this._HistoryListBox.ScrollSkip(-2);//此方法为集合控件的扩展方法。参数为控制滑动的速度。
// scroll.LineRight();
}
if (d < 0)
{
//scroll.LineLeft();
this._HistoryListBox.ScrollSkip(2);
}
scroll.ScrollToTop();
}
}
第三步:定义集合控件的扩展属性和方法。
1 public static class ListBoxExtention 2 { 3 public static double GetHorizontalOffset(DependencyObject obj) 4 { 5 return (double)obj.GetValue(HorizontalOffsetProperty); 6 } 7 8 public static void SetHorizontalOffset(DependencyObject obj, double value) 9 { 10 obj.SetValue(HorizontalOffsetProperty, value); 11 } 12 13 /// <summary> 14 /// 动画属性,控制水平方向移动 15 /// </summary> 16 public static readonly DependencyProperty HorizontalOffsetProperty = DependencyProperty.RegisterAttached("HorizontalOffset", typeof(double), typeof(ListBoxExtention), new UIPropertyMetadata(0.0, OnHorizontalOffsetPropertyChanged)); 17 18 static void OnHorizontalOffsetPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args) 19 { 20 ((ScrollViewer)sender).ScrollToHorizontalOffset((double)args.NewValue); 21 } 22 23 24 25 public static double GetVerticalOffset(DependencyObject obj) 26 { 27 return (double)obj.GetValue(VerticalOffsetProperty); 28 } 29 30 public static void SetVerticalOffset(DependencyObject obj, double value) 31 { 32 obj.SetValue(VerticalOffsetProperty, value); 33 } 34 35 // 用一个依赖属性作为verticaloffset存储器. 这使动画, 样式,绑定, 等等及其他 36 public static readonly DependencyProperty VerticalOffsetProperty =DependencyProperty.RegisterAttached("VerticalOffset", typeof(double), typeof(ListBoxExtention), new UIPropertyMetadata(0.0, OnVerticalOffsetPropertyChanged)); 37 38 static void OnVerticalOffsetPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args) 39 { 40 ((ScrollViewer)sender).ScrollToVerticalOffset((double)args.NewValue); 41 42 public static void ScrollToSelectedItem(this ListBox listbox, object selectedItem) 43 { 44 ScrollViewer scrollHost = VisualTreeHelper.GetChild(listbox, 0) as ScrollViewer; 45 for (DependencyObject obj2 = listbox; obj2 != null; obj2 = VisualTreeHelper.GetChild(obj2, 0)) 46 { 47 ScrollViewer viewer = obj2 as ScrollViewer; 48 if (viewer != null) 49 { 50 scrollHost = viewer; 51 break; 52 } 53 } 54 if (scrollHost != null && scrollHost.IsLoaded) 55 { 56 double fromValue = scrollHost.HorizontalOffset; 57 double toValue = 0.0; 58 if (selectedItem != null) 59 { 60 FrameworkElement visual = listbox.ItemContainerGenerator.ContainerFromItem(selectedItem) as FrameworkElement; 61 if (visual != null) 62 { 63 Vector vector = VisualTreeHelper.GetOffset(visual); 64 toValue = (visual.ActualWidth - scrollHost.ViewportWidth) / 2 + vector.X; 65 } 66 } 67 DoubleAnimation animation = new DoubleAnimation(fromValue, toValue, new TimeSpan(0, 0, 0, 0, 500), FillBehavior.HoldEnd); 68 scrollHost.BeginAnimation(ListBoxExtention.HorizontalOffsetProperty, animation); 69 } 70 } 71 72 73 74 public static void ScrollSkip(this ListBox listbox, int count) 75 { 76 ScrollViewer scrollHost = VisualTreeHelper.GetChild(listbox, 0) as ScrollViewer; 77 for (DependencyObject obj2 = listbox; obj2 != null; obj2 = VisualTreeHelper.GetChild(obj2, 0)) 78 { 79 ScrollViewer viewer = obj2 as ScrollViewer; 80 if (viewer != null) 81 { 82 scrollHost = viewer; 83 break; 84 } 85 } 86 if (scrollHost != null && scrollHost.IsLoaded) 87 { 88 double fromHorizontalOffset = scrollHost.HorizontalOffset; 89 double toHorizontalOffset = 0.0; 90 double fromVerticalOffset = scrollHost.VerticalOffset; 91 double toVerticalOffset = 0.0; 92 toHorizontalOffset = (scrollHost.ExtentWidth / listbox.Items.Count) * count + fromHorizontalOffset; 93 toVerticalOffset = (scrollHost.ExtentHeight / listbox.Items.Count) * count + fromVerticalOffset; 94 95 if (ScrollViewer.GetHorizontalScrollBarVisibility(listbox) != ScrollBarVisibility.Disabled) 96 { 97 DoubleAnimation animation = new DoubleAnimation(fromHorizontalOffset, toHorizontalOffset, new TimeSpan(0, 0, 0, 0, 800), FillBehavior.HoldEnd); 98 scrollHost.BeginAnimation(ListBoxExtention.HorizontalOffsetProperty, animation); 99 } 100 if (ScrollViewer.GetVerticalScrollBarVisibility(listbox) != ScrollBarVisibility.Disabled) 101 { 102 DoubleAnimation animation = new DoubleAnimation(fromVerticalOffset, toVerticalOffset, new TimeSpan(0, 0, 0, 0, 800), FillBehavior.HoldEnd); 103 scrollHost.BeginAnimation(ListBoxExtention.VerticalOffsetProperty, animation); 104 } 105 } 106 } 107 108 public static void ScrollSkip_Double(this ListBox listbox, Double count) 109 { 110 ScrollViewer scrollHost = VisualTreeHelper.GetChild(listbox, 0) as ScrollViewer; 111 for (DependencyObject obj2 = listbox; obj2 != null; obj2 = VisualTreeHelper.GetChild(obj2, 0)) 112 { 113 ScrollViewer viewer = obj2 as ScrollViewer; 114 if (viewer != null) 115 { 116 scrollHost = viewer; 117 break; 118 } 119 } 120 if (scrollHost != null && scrollHost.IsLoaded) 121 { 122 double fromHorizontalOffset = scrollHost.HorizontalOffset; 123 double toHorizontalOffset = 0.0; 124 double fromVerticalOffset = scrollHost.VerticalOffset; 125 double toVerticalOffset = 0.0; 126 toHorizontalOffset = (scrollHost.ExtentWidth / listbox.Items.Count) * count + fromHorizontalOffset; 127 toVerticalOffset = (scrollHost.ExtentHeight / listbox.Items.Count) * count + fromVerticalOffset; 128 129 if (ScrollViewer.GetHorizontalScrollBarVisibility(listbox) != ScrollBarVisibility.Disabled) 130 { 131 DoubleAnimation animation = new DoubleAnimation(fromHorizontalOffset, toHorizontalOffset, new TimeSpan(0, 0, 0, 0, 800), FillBehavior.HoldEnd); 132 scrollHost.BeginAnimation(ListBoxExtention.HorizontalOffsetProperty, animation); 133 } 134 if (ScrollViewer.GetVerticalScrollBarVisibility(listbox) != ScrollBarVisibility.Disabled) 135 { 136 DoubleAnimation animation = new DoubleAnimation(fromVerticalOffset, toVerticalOffset, new TimeSpan(0, 0, 0, 0, 800), FillBehavior.HoldEnd); 137 scrollHost.BeginAnimation(ListBoxExtention.VerticalOffsetProperty, animation); 138 } 139 } 140 } 141 }