总的来说,WPF对于UI方面的支持还是挺强大的,可以很方便地制作精美的UI,
可是习惯传统WinForm开发的程序员,一开始接触WPF可能会不太适应。
例如,传统WinForm中很多控件都有Text这个属性,大部分也都是继承于Control这个类,
而在WPF中,部分控件是有Text属性的,部分控件是有Content属性而没有Text属性的,
且有的控件是继承于Control,有的控件是继承于FrameworkElement,
第一次接触WPF的人可能会觉得有点乱,不太适应。
不过,不适应也只是暂时的,随着使用时间的增长,适应那也是迟早的事情了。
不过呢,大多数人会发现一个问题,就是在WPF中大部分控件都没有Click事件,也就是鼠标单击事件。
在开发过程中,有的时候我们需要自定义按钮样式,传统WinForm一般是放一个Image,然后加上Click事件来模拟按钮,
然而在WPF中我们并不能简单地这么做,因为WPF中的Image没有Click事件。
虽然WPF中的Button支持Click事件且能通过设置背景图片来自定义样式,可是Button同时还会有个Hover的效果,我们又不需要这个效果,会影响美观,
要去掉这个Hover效果只能通过Style的方式来修改,对于初级水平的人员来说,可能会有点难。
最终比较简单的方式,还是回归到Image控件+模拟的Click事件来实现这个效果。
很多人会使用MouseLeftButtonDown或MouseLeftButtonUp来模拟这个Click事件,但实际上都不完美,因为都有缺点。
传统的Click事件,是在鼠标放开的一瞬间出发的,也就是说按照Down->Click->Up的顺序触发事件,
触发Down事件的时候Click事件并没有触发,只有在触发Up事件的之前会同时触发Click事件。
当然,有的程序语言中,是按照Down->Up->Click的顺序触发事件的,反正至少在.NET中是按照Down->Click->Up的顺序触发事件。
按照这个顺序来看的话,直接用MouseLeftButtonDown代替Click肯定是不妥的;
如果用MouseLeftButtonUp来代替Click呢,一般情况下问题也不大,但如果我在别的地方点击再移动到Image上再Up呢,这个时候就有问题了
我参考这个顺序做了一个模拟Click事件的函数,代码如下:
/// <summary> /// 为目标控件附加一个模拟的鼠标单击事件 /// </summary> /// <param name="control">需要附加事件的控件</param> /// <param name="handler">鼠标单击事件的处理函数</param> /// <remarks> /// By 风の雪 /// http://www.canaansky.com/ /// 在目标控件上MouseDown->MouseLeave->MouseEnter->MouseUp同样有效 /// </remarks> bool EmulateClickEvent(FrameworkElement control, MouseButtonEventHandler handler) { if (control == null || handler == null) return false; int status = 0; control.MouseEnter += delegate { if (status == 0) status = -1; }; control.MouseLeave += delegate { status[0] = 0; }; control.MouseLeftButtonDown += delegate { status = 1; }; control.MouseLeftButtonUp += delegate(object sender, MouseButtonEventArgs e) { if (status > 0) handler(sender, e); status = 0; }; return true; }
调用方法嘛,很简单的,调用该函数,同时传递目标控件和事件处理函数即可,如:
Image image = new Image(); EmulateClickEvent(image, ImageOnClick); void ImageOnClick(object sender, MouseButtonEventArgs e) { MessageBox.Show("Hello World!"); }
注意一下,就是这个函数没有处理双击时情景,所以默认情况下出发双击事件的时候会同时触发两次单击,请自行处理这种情况。