此文章意在解决在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();
            }
}

第三步:定义集合控件的扩展属性和方法。

  public static class ListBoxExtention
{
public static double GetHorizontalOffset(DependencyObject obj)
{
return (double)obj.GetValue(HorizontalOffsetProperty);
} public static void SetHorizontalOffset(DependencyObject obj, double value)
{
obj.SetValue(HorizontalOffsetProperty, value);
} /// <summary>
/// 动画属性,控制水平方向移动
/// </summary>
public static readonly DependencyProperty HorizontalOffsetProperty = DependencyProperty.RegisterAttached("HorizontalOffset", typeof(double), typeof(ListBoxExtention), new UIPropertyMetadata(0.0, OnHorizontalOffsetPropertyChanged)); static void OnHorizontalOffsetPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
{
((ScrollViewer)sender).ScrollToHorizontalOffset((double)args.NewValue);
} public static double GetVerticalOffset(DependencyObject obj)
{
return (double)obj.GetValue(VerticalOffsetProperty);
} public static void SetVerticalOffset(DependencyObject obj, double value)
{
obj.SetValue(VerticalOffsetProperty, value);
} // 用一个依赖属性作为verticaloffset存储器. 这使动画, 样式,绑定, 等等及其他
public static readonly DependencyProperty VerticalOffsetProperty =DependencyProperty.RegisterAttached("VerticalOffset", typeof(double), typeof(ListBoxExtention), new UIPropertyMetadata(0.0, OnVerticalOffsetPropertyChanged)); static void OnVerticalOffsetPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
{
((ScrollViewer)sender).ScrollToVerticalOffset((double)args.NewValue); public static void ScrollToSelectedItem(this ListBox listbox, object selectedItem)
{
ScrollViewer scrollHost = VisualTreeHelper.GetChild(listbox, ) as ScrollViewer;
for (DependencyObject obj2 = listbox; obj2 != null; obj2 = VisualTreeHelper.GetChild(obj2, ))
{
ScrollViewer viewer = obj2 as ScrollViewer;
if (viewer != null)
{
scrollHost = viewer;
break;
}
}
if (scrollHost != null && scrollHost.IsLoaded)
{
double fromValue = scrollHost.HorizontalOffset;
double toValue = 0.0;
if (selectedItem != null)
{
FrameworkElement visual = listbox.ItemContainerGenerator.ContainerFromItem(selectedItem) as FrameworkElement;
if (visual != null)
{
Vector vector = VisualTreeHelper.GetOffset(visual);
toValue = (visual.ActualWidth - scrollHost.ViewportWidth) / + vector.X;
}
}
DoubleAnimation animation = new DoubleAnimation(fromValue, toValue, new TimeSpan(, , , , ), FillBehavior.HoldEnd);
scrollHost.BeginAnimation(ListBoxExtention.HorizontalOffsetProperty, animation);
}
} public static void ScrollSkip(this ListBox listbox, int count)
{
ScrollViewer scrollHost = VisualTreeHelper.GetChild(listbox, ) as ScrollViewer;
for (DependencyObject obj2 = listbox; obj2 != null; obj2 = VisualTreeHelper.GetChild(obj2, ))
{
ScrollViewer viewer = obj2 as ScrollViewer;
if (viewer != null)
{
scrollHost = viewer;
break;
}
}
if (scrollHost != null && scrollHost.IsLoaded)
{
double fromHorizontalOffset = scrollHost.HorizontalOffset;
double toHorizontalOffset = 0.0;
double fromVerticalOffset = scrollHost.VerticalOffset;
double toVerticalOffset = 0.0;
toHorizontalOffset = (scrollHost.ExtentWidth / listbox.Items.Count) * count + fromHorizontalOffset;
toVerticalOffset = (scrollHost.ExtentHeight / listbox.Items.Count) * count + fromVerticalOffset; if (ScrollViewer.GetHorizontalScrollBarVisibility(listbox) != ScrollBarVisibility.Disabled)
{
DoubleAnimation animation = new DoubleAnimation(fromHorizontalOffset, toHorizontalOffset, new TimeSpan(, , , , ), FillBehavior.HoldEnd);
scrollHost.BeginAnimation(ListBoxExtention.HorizontalOffsetProperty, animation);
}
if (ScrollViewer.GetVerticalScrollBarVisibility(listbox) != ScrollBarVisibility.Disabled)
{
DoubleAnimation animation = new DoubleAnimation(fromVerticalOffset, toVerticalOffset, new TimeSpan(, , , , ), FillBehavior.HoldEnd);
scrollHost.BeginAnimation(ListBoxExtention.VerticalOffsetProperty, animation);
}
}
} public static void ScrollSkip_Double(this ListBox listbox, Double count)
{
ScrollViewer scrollHost = VisualTreeHelper.GetChild(listbox, ) as ScrollViewer;
for (DependencyObject obj2 = listbox; obj2 != null; obj2 = VisualTreeHelper.GetChild(obj2, ))
{
ScrollViewer viewer = obj2 as ScrollViewer;
if (viewer != null)
{
scrollHost = viewer;
break;
}
}
if (scrollHost != null && scrollHost.IsLoaded)
{
double fromHorizontalOffset = scrollHost.HorizontalOffset;
double toHorizontalOffset = 0.0;
double fromVerticalOffset = scrollHost.VerticalOffset;
double toVerticalOffset = 0.0;
toHorizontalOffset = (scrollHost.ExtentWidth / listbox.Items.Count) * count + fromHorizontalOffset;
toVerticalOffset = (scrollHost.ExtentHeight / listbox.Items.Count) * count + fromVerticalOffset; if (ScrollViewer.GetHorizontalScrollBarVisibility(listbox) != ScrollBarVisibility.Disabled)
{
DoubleAnimation animation = new DoubleAnimation(fromHorizontalOffset, toHorizontalOffset, new TimeSpan(, , , , ), FillBehavior.HoldEnd);
scrollHost.BeginAnimation(ListBoxExtention.HorizontalOffsetProperty, animation);
}
if (ScrollViewer.GetVerticalScrollBarVisibility(listbox) != ScrollBarVisibility.Disabled)
{
DoubleAnimation animation = new DoubleAnimation(fromVerticalOffset, toVerticalOffset, new TimeSpan(, , , , ), FillBehavior.HoldEnd);
scrollHost.BeginAnimation(ListBoxExtention.VerticalOffsetProperty, animation);
}
}
}
}

WPF ItemsControl 控件支持鼠标滚轮滑动的更多相关文章

  1. WPF ListView控件设置奇偶行背景色交替变换以及ListViewItem鼠标悬停动画

    原文:WPF ListView控件设置奇偶行背景色交替变换以及ListViewItem鼠标悬停动画 利用WPF的ListView控件实现类似于Winform中DataGrid行背景色交替变换的效果,同 ...

  2. WPF 在image控件用鼠标拖拽出矩形

    原文:WPF 在image控件用鼠标拖拽出矩形 版权声明:博客已迁移到 http://lindexi.gitee.io 欢迎访问.如果当前博客图片看不到,请到 http://lindexi.gitee ...

  3. C# WPF 歌词控件(支持逐字定位描色效果)

    原文:C# WPF 歌词控件(支持逐字定位描色效果) 之前做了一个模仿网易云歌词的控件,实现了加载网易云歌词并能随音乐播放进度定位歌词.今天呢将在这个控件的基础上增加逐字定位描色功能,如下图效果(QQ ...

  4. WPF界面开发者注意啦!Scheduler控件支持时区功能了,你get了吗

    DevExpress广泛应用于ECM企业内容管理. 成本管控.进程监督.生产调度,在企业/政务信息化管理中占据一席重要之地.通过DevExpress WPF Controls,您能创建有着强大互动功能 ...

  5. 如何让DbGrid支持鼠标滚轮滚动

    如何让DbGrid支持鼠标滚轮滚动 在主窗体上加一个ApplicationEvents控件(控件在Additional面板中), 在它的OnMessage事件中加入下述代码,一切搞定-! proced ...

  6. WPF第三方控件盘点

    WPF统一的编程模型.语言和框架,实现了界面设计人员和开发人员工作可以分离的境界,鉴于WPF强大的优势,且一直是开发者关注的地方,下面和大家分享基于WPF项目开发需要用到的第三方控件,包括业界最受好评 ...

  7. 创建 WPF 工具箱控件

    创建 WPF 工具箱控件 WPF (Windows Presentation Framework) 工具箱控件模板允许您创建 WPF 控件,会自动添加到 工具箱 安装扩展的安装. 本主题演示如何使用模 ...

  8. WPF常用控件应用demo

    WPF常用控件应用demo 一.Demo 1.Demo截图如下: 2.demo实现过程 总体布局:因放大缩小窗体,控件很根据空间是否足够改变布局,故用WrapPanel布局. <ScrollVi ...

  9. 一款开源免费的WPF图表控件ModernuiCharts

    一款简洁好看的Chart控件  支持WPF.silverlight.Windows8  ,基本够用,主要是开源免费的.(商业控件ComponentOne for WPF要4w多呢) This proj ...

随机推荐

  1. 字符串逆转(递归和非递归java)

    package 乒乒乓乓; public class 递归逆转字符串 {    //非递归逆转    public static String reverse(String s)    {       ...

  2. Java笔记(十四)……抽象类与接口

    抽象类概念 抽象定义: 抽象就是从多个事物中将共性的,本质的内容抽取出来. 例如:狼和狗共性都是犬科,犬科就是抽象出来的概念. 抽象类: Java中可以定义没有方法体的方法,该方法的具体实现由子类完成 ...

  3. vijosP1447 开关灯泡

    vijosP1447 开关灯泡 链接:https://vijos.org/p/1447 [思路] 数学+高精度. 分析题目:题中有言,i时刻将其所有倍数的灯熄灭,由此得知一个数有多少个倍数就会被操作多 ...

  4. CF_216_Div_2

    比赛链接:http://codeforces.com/contest/369 369C - Valera and Elections: 这是一个树上问题,用深搜,最开始贪心想得是只加叶子节点,找到一个 ...

  5. java枚举enum

    http://www.cnblogs.com/wenruo/p/5349614.html java的枚举通过关键字enum实现.可以理解为一个类,不过这个类由编译器自动加了一些方法. static v ...

  6. hdu3681--Prison Break(TSP+二分)

    好难的一道题. 题意:一个机器人要逃出监狱,每走一步消耗一点电量,初始时电量是满的.给一个n*m(n,m<=15)的字符数组代表监狱,F代表起始点,G代表补充满电量,每个G只能补充一次,Y代表开 ...

  7. 多组radio传值注意事项

    多组radio传值,每组的radio name必须不同,否则所有的radio将被视为一组,传值时只会传其中一组的值到后台,如果这时你用数组接收从前台传过来的值并使用,就会报数组越界异常

  8. Jquery常用方法篇(一)

    1.add方法:将匹配的元素添加到当前的jquery对象集合中. 语法 add(expr,[context]) 参数1表示 用于匹配元素选择器(待添加的对象),或者用于动态生成的HTML代码(字符串) ...

  9. jQuery事件绑定的最佳实践

    如果你经常使用jQuery,那么你也许很熟悉事件绑定.这是很基本的东西,但是深入一点,你就能够找到机会让你事件驱动的代码变得不太零碎,并且更容易管理. 更好的选择器策略 让我们从基础的例子开始.下面的 ...

  10. vue相关

    勾三股四的vue+webpack实战:http://jiongks.name/blog/just... 用Vue构建一个Notes App:https://coligo.io/learn-vuex-. ...