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

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

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

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

public class EventWaiter
{
private DateTime _lastTime; public EventWaiter(double seconds)
{
Interval = TimeSpan.FromSeconds(seconds);
} public EventWaiter(TimeSpan interval)
{
Interval = interval;
} public EventWaiter()
{
Interval = TimeSpan.FromSeconds(0.1d);
} //间隔
public TimeSpan Interval { get; set; } public bool IsEnabled
{
get
{
if(DateTime.Now - _lastTime > Interval)
{
_lastTime = DateTime.Now;
return true;
}
return false;
}
} public void Reset()
{
_lastTime = DateTime.Now;
}
}

大概用法是这样的:


var waiter = new EventWaiter(); var button = new Button();
button.Click += OnClick; private void OnClick(object sender,RoutedEventArgs e)
{
if(waiter.IsEnabled)
{
//do something
}
}

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

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

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

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

public class EventDelayer
{
private DispatcherTimer _timer; public EventDelayer(double seconds) : this(TimeSpan.FromSeconds(seconds))
{
} public EventDelayer(TimeSpan interval)
{
_timer = new DispatcherTimer();
_timer.Tick += _timer_Tick;
Interval = interval;
} public EventDelayer() : this(0.1)
{
} public TimeSpan Interval
{
get => _timer.Interval;
set => _timer.Interval = value;
} public bool ResetWhenDelayed { get; set; } public void Delay()
{
if (!_timer.IsEnabled)
{
_timer.Start();
}
else
{
if (ResetWhenDelayed)
{
_timer.Stop();
_timer.Start();
}
}
} private void _timer_Tick(object sender, object e)
{
if (_timer.IsEnabled)
{
_timer.Stop();
}
OnArrived();
} public event EventHandler Arrived;
protected void OnArrived()
{
Arrived?.Invoke(this, EventArgs.Empty);
} }

用法大概是这个样子:

var delayer = new EventDelayer();

delayer.Arrived += OnArrived;

this.SizeChanged += OnSizeChanged;

private void OnSizeChanged(object sender, SizeChangedEventArgs e)
{
delayer.Delay();
} private void OnArrived(object sender,EventArgs args)
{
//do something
}

炒鸡完美。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. 李清华201772020113《面向对象程序设计(Java)》第六周学习总结

    第一部分 理论知识 1.继承 用已有类来构建新类的一种机制.新类可以继承父类的方法和域,同时可以在新类中添加新的方法和域. 已有类称为:超类.基类或父类.新类称作:子类.派生类或孩子类. 子类的构造器 ...

  2. SQLite在Android程序中的使用方法,SQLite的增删查改方法

    Sqlite: 1.一款用来实现本地数据存储的轻量级数据管理工具,是众多用来实现数据库管理的工具之一. 2.Android已经将SQLite的代码功能吸收在它的系统中,我们可以直接在Android程序 ...

  3. 一篇面经(BAT面试)(转)

    0. 写在之前 首先呢我的面试经历和一些面霸和收割机的大神相比绝不算丰富,但我这三个月应该能代表很大一部分人的心路历程:从无忧无虑也无知的状态,然后遭遇挫败,跌入低谷,连续数天的黑暗,慢慢调整,逼着自 ...

  4. Delphi TXLSReadWriteII导出Excel

    TXLSReadWriteII导出Excle (有点复杂,可以自己简化一下,直接从项目中抓取的) procedure TformSubReport.DataToExcel(_Item: Integer ...

  5. Linux-vim文本编辑器

    [Vim文本编辑器] vim的三种模式:一般模式.编辑模式.命令模式. * 一般模式: 当你vim filename 编辑一个文件时,一进入该文件就是一般模式了.在这个模式下,你可以做的操作有,上下移 ...

  6. 微信小程序---分包加载(subpackages)及报错

    某些情况下,开发者需要将小程序划分成不同的子包,在构建时打包成不同的分包,用户在使用时按需进行加载. 分包很简单,具体步骤如下: 在app.json中,创建subPackages,root表示分包A的 ...

  7. Unity之AssetBundle打包

    AssetBundle Resources:表示U3D自动将资源打成一个AssetBundle包,所有放在Resources下的文件夹都会打成一个AssetBundle包,资源非常大,Resource ...

  8. javascript中的类型检测

    最常见的是使用 typeof 来判断数据类型 可以区分4种基本类型,即 “number”,”string”,”undefined”,”boolean”,第5种基本类型null类型返回值为object( ...

  9. JS 操作样式 style

    1. 任何支持 style 特性的 HTML 元素在 JavaScript 中都对应着有一个 style 属性,指向一个 CSSStyleDeclaration 的一个实例对象,包含该元素的内嵌sty ...

  10. Python设计模式 - 创建型 - 单例模式(Singleton) - 十种

    对于很多开发人员来说,单例模式算是比较简单常用.也是最早接触的设计模式了,仔细研究起来单例模式似乎又不像看起来那么简单.我们知道单例模式适用于提供全局唯一访问点,频繁需要创建及销毁对象等场合,的确方便 ...