UWP忽略短时间内重复触发的事件

原文:UWP忽略短时间内重复触发的事件

原链接: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

原文地址:https://www.cnblogs.com/lonelyxmas/p/10129675.html

时间: 2024-11-07 22:42:07

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

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

分享个combotree允许多选的时候onSelect事件(通常是点击“+”号时)会重复触发onCheck事件的蠢解决办法是: 1.弄一个全局变量: var loading = false; //表示在触发combotree各种事件时是否遍历树: 2.设置onSelect时不做任何操作: $("input[name='XXXXX']").combotree({ ... onSelect: function(node) { return; }, ... }); 3.设置onBeforeL

干掉微信小程序-避免多次点击,重复触发事件

干掉微信小程序-避免多次点击,重复触发事件 问题描述 开发小程序时,或者说是在做前端的时候,我们经常会遇到当用户点击某个按钮时,没有得到反馈的话,大部分用户都会接着点击,这就会造成前端接收到多次请求的响应. 这主要是因为后端api请求需要时间,导致用户以为没点击到或者是页面假死,在上次请求还没处理完,就再次点击按钮. 所以,接下来说说,在微信小程序中避免多次点击,重复触发事件的两种思路. 解决方法一: 使用 wx.showLoading 在请求执行之前显示一个加载框,请求完成后再关闭加载框. j

金蝶VB插件,单据保存时总是触发GetFocus事件

在做金蝶插件时,在保存时,总是触发GetFocus事件,让人很伤心啊 Private Sub m_BillInterface_GotFocus(ByVal sKey As String, ByVal dctData As KFO.IDictionary, ByVal curDspValue As Variant, ByVal Col As Long, ByVal Row As Long, Cancel As Boolean) If (Row > 0 And r <> -110 And r

DICOM:剖析Orthanc中的Web Server,Mongoose之“连接请求触发的事件序列”(二)

背景: Orthanc是本专栏中介绍过的一款新型DICOM服务器,具有轻量级.支持REST的特性,可将任意运行Windows和Linux系统的计算机变成DICOM服务器,即miniPACS.Orthanc内嵌多种模块,数据库管理简单,且不依赖于第三方软件.因此通过剖析Orthanc源码可以学习到搭建DICOM系统中的各个环节,例如SQLite嵌入型数据库.GoogleLog日志库.DCMTK医学DICOM库,以及近期要介绍的开源Web Server,Mongoose. 题记: 近期计划参照官网剖

如何隐藏日历列表的重复和全天事件栏目

因为项目需要,需要隐藏重复和全天事件栏目,在列表设置无法隐藏,采用sharepoint Manager2013也无法隐藏.如下图: 这里采用Jquery去隐藏找到日历的NewForm.aspx,如下图: 打开后添加[内容编辑器]的webpart,如下图: 编辑HTML <script src="/_layouts/15/JunHe_Master/js/jquery-1.9.1.js" type="text/javascript"></script&

Unity3D导入外部任务模型无法触发鼠标事件解决方案

前几日 在做U3D测试的时候 导入了网上的一个人物模型 但是后来发现无论如何该模型都无法响应诸如:OnMouseDown 这些鼠标事件 又用U3D自带的水管工做了测试 发现不是我系统的问题= = 水管工对鼠标事件还是有反应的 遂百度之 查到的解决方法是 在Project窗口中选中导入FBX模型,在右边的Inspector中选中Generate Colliders 说是因为U3D默认导入的模型没有启动碰撞机Colliders 但是------ 我在确定模型的Generate Colliders被选

Dynamics CRM Form表单中通过javascript抓取触发change事件字段的属性名

通过以下这段代码能够抓取到change的事件源,从而推断出是哪个属性字段触发的事件, function change(pContext) {var fieldName=pContext.getEventSource().getName(); } 在字段的事件设置中须要将下框中复选框的勾勾上.很多其它的信息可參见SDK.

Spring透过ApplicationListener来触发contextrefreshedevent事件

Spring通过ApplicationListener接口来触发contextrefreshedevent事件在开发时有时候需要在整个应用开始运行时执行一些特定代码,比如初始化环境,准备测试数据.加载一些数据到内存等等. 在Spring中可以通过ApplicationListener来实现相关的功能,加载完成后触发contextrefreshedevent事件(上下文件刷新事件) 例如:定时任务 上述中解决了一个问题: 会存在一个问题,在web 项目中(spring mvc),系统会存在两个容器

div无法触发blur事件解决的方法

默认情况下div无法获取焦点,无法触发focus与blur事件,推測span,a等标签也无法触发焦点事件(input:button.及button标签能够触发) 怎样使div触发blur事件:能够给div加上tabindex属性 在线演示:http://sandbox.runjs.cn/show/e0bvfcag 源代码: <!DOCTYPE html> <html lang="en"> <head> <meta charset="U