原链接:UWP忽略短时间内重复触发的事件 - 超威蓝火

做移动端开发的可能都会遇到这种需求,当用户点击一个按钮之后,由于没有异步,或者设备性能很差等等原因,程序卡住了。但是用户不知道是咋回事啊,就开始狂点按钮,结果请求很多次资源,或者构造了很多重复视图。安卓上有很多介绍如何忽略重复点击的情况,uwp里我好像还没找到,那接下来就说一说我的方法吧。

首先是官方最常用的,从Windows诞生之初用到现在的,点击按钮之后把他Disable掉,等完成了在Enable。其实这算是最好的选择了,但是总归是麻烦了一些,尤其是在MVVM的时候,每个Button都要单独绑定一个IsEnabled,所以接下来就仿照安卓上的通用处理方法试一下。

首先创建一个类,我们就叫他EventWaiter吧,里面维护一个LastTime,一个IsEnabled,事件可以判断这个IsEnabled来知道,上一次点击和这一次点击的间隔是不是过短,从而决定是否要执行。

  1. public class EventWaiter
  2. {
  3. private DateTime _lastTime;
  4. public EventWaiter(double seconds)
  5. {
  6. Interval = TimeSpan.FromSeconds(seconds);
  7. }
  8. public EventWaiter(TimeSpan interval)
  9. {
  10. Interval = interval;
  11. }
  12. public EventWaiter()
  13. {
  14. Interval = TimeSpan.FromSeconds(0.1d);
  15. }
  16. //间隔
  17. public TimeSpan Interval { get; set; }
  18. public bool IsEnabled
  19. {
  20. get
  21. {
  22. if(DateTime.Now - _lastTime > Interval)
  23. {
  24. _lastTime = DateTime.Now;
  25. return true;
  26. }
  27. return false;
  28. }
  29. }
  30. public void Reset()
  31. {
  32. _lastTime = DateTime.Now;
  33. }
  34. }

大概用法是这样的:


  1. var waiter = new EventWaiter();
  2. var button = new Button();
  3. button.Click += OnClick;
  4. private void OnClick(object sender,RoutedEventArgs e)
  5. {
  6. if(waiter.IsEnabled)
  7. {
  8. //do something
  9. }
  10. }

接下来就是第三种需求了。对于安卓iOS来说,很少有SizeChanged,但是UWP不一样啊,UWP能窗口运行啊,所以在一些要响应SizeChanged,在窗口大小改变的时候做一些很重操作的时候,拖拽窗口就会变得非常卡,所以我现在想忽略拖动窗口的中间过程,只让他响应最后状态。而上面的EventWaiter,是一段时间内只响应第一次事件的触发,和我们的需求是完全反着的。

这时候就要请救星:DispatcherTimer出来了(感谢小竹)。

大致思路呢,按时间顺序叙述,是当原事件触发时,让Timer开始运行;第二次触发事件时判断Timer是否运行,如果正在运行呢,就停掉重新启动,相当于重置了计时器;等Timer第一次跑完,执行Tick的时候停掉Timer,并且激活内部的事件去做真正的操作。

我们再弄个新的类,起个名字叫EventDelayer(原谅我起名困难),里面需要维护一个DispatcherTimer,还要一个事件Arrived负责在最后被触发,和一个Delay()方法,负责进入触发判断。

  1. public class EventDelayer
  2. {
  3. private DispatcherTimer _timer;
  4. public EventDelayer(double seconds) : this(TimeSpan.FromSeconds(seconds))
  5. {
  6. }
  7. public EventDelayer(TimeSpan interval)
  8. {
  9. _timer = new DispatcherTimer();
  10. _timer.Tick += _timer_Tick;
  11. Interval = interval;
  12. }
  13. public EventDelayer() : this(0.1)
  14. {
  15. }
  16. public TimeSpan Interval
  17. {
  18. get => _timer.Interval;
  19. set => _timer.Interval = value;
  20. }
  21. public bool ResetWhenDelayed { get; set; }
  22. public void Delay()
  23. {
  24. if (!_timer.IsEnabled)
  25. {
  26. _timer.Start();
  27. }
  28. else
  29. {
  30. if (ResetWhenDelayed)
  31. {
  32. _timer.Stop();
  33. _timer.Start();
  34. }
  35. }
  36. }
  37. private void _timer_Tick(object sender, object e)
  38. {
  39. if (_timer.IsEnabled)
  40. {
  41. _timer.Stop();
  42. }
  43. OnArrived();
  44. }
  45. public event EventHandler Arrived;
  46. protected void OnArrived()
  47. {
  48. Arrived?.Invoke(this, EventArgs.Empty);
  49. }
  50. }

用法大概是这个样子:

  1. var delayer = new EventDelayer();
  2. delayer.Arrived += OnArrived;
  3. this.SizeChanged += OnSizeChanged;
  4. private void OnSizeChanged(object sender, SizeChangedEventArgs e)
  5. {
  6. delayer.Delay();
  7. }
  8. private void OnArrived(object sender,EventArgs args)
  9. {
  10. //do something
  11. }

炒鸡完美。github:https://github.com/cnbluefire/ReaderView/tree/master/ReaderView/Common/Helpers

UWP忽略短时间内重复触发的事件的更多相关文章

  1. EasyUI中combotree允许多选的时候onSelect事件会重复触发onCheck事件

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAgEAAADkCAIAAACOkmAuAAAgAElEQVR4nO2dW2wc15nnO0EQBJsdzA

  2. javascript避免dom事件重复触发

    /** * 为指定控件添加限制性事件, 该事件在触发之后, 会被移除, 并在指定的时间间隔后, 重新绑定, 适用于避免控件事件被误操作重复触发的场景 * @param {String} domID 要 ...

  3. jQuery 防止相同的事件快速重复触发

    重复触发就是防止用户重复点击提交数据了,我们一般都是点击之后没反应会再次点击了,这个不但要从用户体验上来做好,还在要js或php程序脚本上做好,让用户知道点击是己提交服务器正在处理,下面我就整理从脚本 ...

  4. echarts 图的点击事件(含:点击重复触发的问题及其解决方法)

    今天用echarts的时候发现一个问题 鼠标指向不同地市触发一个事件展示该地区趋势图  但是但是后台中不管我第几次鼠标指向都会触发两次指向事件 现在贴出解决办法: 问题完美解决.但是为什么会调用两次, ...

  5. 实现textbox文本页面改变触发textchanged事件,代码里修改不触发

    今天弄控件遇到一个问题,就是TextChanged,如果在代码里或在页面修改修改text值,就会触发事情,但如果在textchanged里修改text,它会不会触发呢,不会,我调试跟踪,并没发现它会重 ...

  6. Echarts如何添加鼠标点击事件?防止重复触发点击事件

    Echarts如何添加鼠标点击事件? 1.通常我们只使用了以下代码,通过配置项和数据显示图表. var myChart = echarts.init(document.getElementById(' ...

  7. 关于Android避免按钮重复点击事件

    最近测试人员测试我们的APP的时候,喜欢快速点击某个按钮,出现一个页面出现多次,测试人员能不能禁止这样.我自己点击了几下,确实存在这个问题,也感觉用户体验不太好.于是乎后来我搜了下加一个方法放在我们U ...

  8. C# Winform 拦截关闭按钮触发的事件

    用户关闭软件时,软件一般会给“是否确认关闭”的提示. 通常,我们把它写在FormClosing 事件中,如果确定关闭,就关闭:否则把FormClosingEventArgs 的 Cancel 属性设置 ...

  9. GridView点击行触发SelectedIndexChanged事件

    1.在<% @Page ...... %>指令中添加 EnableEventValidation="false" 2.在RowDataBound事件中添加 protec ...

随机推荐

  1. Python面向对象编程(下)

    本文主要通过几个实例介绍Python面向对象编程中的封装.继承.多态三大特性. 封装性 我们还是继续来看下上文中的例子,使用Student类创建一个对象,并修改对象的属性.代码如下: #-*- cod ...

  2. 搭建mxnet-gpu docker的pyhon remote kernel

    起因 最近看mxnet的东西,打算给实验室的机器装一个mxnet的环境,无奈实验室里面机器已经装了tensorflow,运行了好久了,环境比较老.而mxnet可是支持最新的cuda9.1和cudnn7 ...

  3. MySQL InnoDB内存压力判断以及存在的疑问

    本文出处:http://www.cnblogs.com/wy123/p/7259866.html(保留出处并非什么原创作品权利,本人拙作还远远达不到,仅仅是为了链接到原文,因为后续对可能存在的一些错误 ...

  4. 最新ceph集群常用命令梳理

    结合网络.官网.手动查询等多方渠道,整理ceph维护管理常用命令,并且梳理常规命令在使用过程中的逻辑顺序.另外整理期间发现ceph 集群的命令体系有点乱,详细情况各自体验. 一:ceph集群启动.重启 ...

  5. spring @Scheduled 并发

    一.spring定时任务配置 applicationContext.xml:红色代码部分为需要配置的部分. <?xml version="1.0" encoding=&quo ...

  6. [Solution] 950. Reveal Cards In Increasing Order

    Difficulty: Medium Problem In a deck of cards, every card has a unique integer. You can order the de ...

  7. PowerScript语言基础

    注释: 以 "//" 开头,其后书写注释内容,常用于单行注释. "/-/"中间的部分为注释,便于多行说明. //这是一个单行注释 INTEGER I I = I ...

  8. geckodriver问题

    selenium.common.exceptions.WebDriverException: Message: Service geckodriver unexpectedly exited. Sta ...

  9. vue 兼容性——ie家族不支持promise

    解决方案: 安装: cnpm install es6-promise 在 main.js 引入 : polyfill require("es6-promise").polyfill ...

  10. Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.

    Error starting ApplicationContext. To display the conditions report re-run your application with 'de ...