当Timer触发其tick时,如何使TextBox.TextChanged事件不触发?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了当Timer触发其tick时,如何使TextBox.TextChanged事件不触发?相关的知识,希望对你有一定的参考价值。

下面的代码包含两个更新面板,两者都将UpdateMode设置为“Conditional”。一个有Timer触发每5秒,另一个有LabelTextBoxAutoPostBack设置为true),有一个更改标签文本的有线TextChanged事件。计时器不参与页面呈现:它执行心跳和其他日志记录操作。每当用户在文本框中键入输入并且定时器触发时,会触发TextChanged事件,即使回发源自另一个更新面板(带有计时器的更新),也会有效地更改标签文本。我希望只有当文本框由于用户操作而松散焦点时才会触发TextChanged事件。可能吗?或者我应该避免使用System.Web.UI.Timer并使用其他东西?在这种情况下是什么?

<%@ Page Title="Home Page" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true"
    CodeBehind="Default.aspx.cs" Inherits="WebApplication1._Default" %>

<asp:Content ID="HeaderContent" runat="server" ContentPlaceHolderID="HeadContent">
</asp:Content>

<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">

<asp:ScriptManager ID="ScriptManager1" runat="server"
    EnablePartialRendering="true">
</asp:ScriptManager>

<asp:UpdatePanel ID="UpdatePanel1" runat="server"
    ChildrenAsTriggers="False"  UpdateMode="Conditional">

    <ContentTemplate>
        <asp:Timer ID="Timer1" runat="server" ontick="Timer1_Tick"
            Interval="5000"></asp:Timer>
    </ContentTemplate>

    <Triggers>
        <asp:AsyncPostBackTrigger ControlID="Timer1" EventName="Tick" />
    </Triggers>

</asp:UpdatePanel>

<asp:UpdatePanel ID="UpdatePanel2" runat="server"
    ChildrenAsTriggers="False" UpdateMode="Conditional">

    <ContentTemplate>
        <asp:TextBox ID="TextBox1" runat="server" AutoPostBack="True" 
            ontextchanged="TextBox1_TextChanged"></asp:TextBox>
        <asp:Label ID="Label1" runat="server"
            Text="Label"></asp:Label>
    </ContentTemplate>

    <Triggers>
        <asp:AsyncPostBackTrigger ControlID="TextBox1"
            EventName="TextChanged" />
    </Triggers>

</asp:UpdatePanel>

</asp:Content>

代码背后:

    protected void Timer1_Tick(object sender, EventArgs e)
    {
        // Heartbeat, logging and other stuff
    }

    protected void TextBox1_TextChanged(object sender, EventArgs e)
    {
        Label1.Text = TextBox1.Text;
    }
答案

我最终明白回发不太适合与页面渲染无关的后台活动。更简洁的方法是调用WebService或发布到不同的页面。扩展Timer类,我能够实现第二个策略覆盖当计时器滴答时调用的javascript函数,使其能够执行Post到不同的url。请随意指出其他类似行为的ajax控件。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.ComponentModel;
using System.Text;

namespace AjaxExt
{

    [ToolboxData("<{0}:TimerEx runat=server></{0}:TimerEx>")]
    public class TimerEx : Timer
    {
        public const string POST_FIELD = "__TIMEREXDATA";

        public TimerEx()
        {
            TimerMode = TimerMode.DoPostBack;
            PostUrl = "";
            PostData = "";
            PostField = "";
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            if (TimerMode.HasFlag(TimerMode.DoPost) && !String.IsNullOrEmpty(PostUrl))
            {
                string postUrl = PostUrl.StartsWith("/") ? PostUrl : "/" + PostUrl;
                string postField = String.IsNullOrEmpty(PostField) ? POST_FIELD : PostField;
                // Override tick function
                StringBuilder builder = new StringBuilder();
                builder.AppendLine("function pageLoad() {");
                builder.AppendLine("    var timer = $find('" + this.ClientID + "');");
                builder.AppendLine("    timer._doPostback = function () {");
                builder.AppendLine("        $.ajax({");
                builder.AppendLine("            url: "" + postUrl + "",");
            if (String.IsNullOrEmpty(PostData))
                builder.AppendLine("            data: null,");
            else
                builder.AppendLine("            data: { " + postField + ": " + PostData + "},");
                builder.AppendLine("            success: null,");
                builder.AppendLine("            error: null");
                builder.AppendLine("        });");
            if (TimerMode.HasFlag(TimerMode.DoPostBack))
                builder.AppendLine("        __doPostBack(this.get_uniqueID(),'');");
                builder.AppendLine("    };");
                builder.AppendLine("}");

                Page.ClientScript.RegisterClientScriptBlock(typeof(Page), "dopostscript", builder.ToString(), true);
            }
        }

        [DefaultValue(TimerMode.DoPostBack)]
        public TimerMode TimerMode
        {
            get;
            set;
        }

        [DefaultValue("")]
        public string PostUrl
        {
            get;
            set;
        }

        [DefaultValue("")]
        public string PostData
        {
            get;
            set;
        }

        [DefaultValue("")]
        public string PostField
        {
            get;
            set;
        }
    }

    [Flags]
    public enum TimerMode
    {
        DoPost = 1,
        DoPostBack = 2,
        DoBoth = DoPost | DoPostBack
    }
}

它可以添加到页面中,如下所示:

<%@ Register Assembly="AjaxExt" Namespace="AjaxExt" TagPrefix="jaxext" %>

<ajaxext:TimerEx ID="PingTimer" runat="server" PostUrl="HeartBeat.aspx" 
    TimerMode="DoPost" Interval="10000" />

以上是关于当Timer触发其tick时,如何使TextBox.TextChanged事件不触发?的主要内容,如果未能解决你的问题,请参考以下文章

C#中怎么使系统托盘的气泡每隔5秒显示一次

WinForm应用Timer定时器(基本)

C#事件学习

在Timer Tick C#表单上更改DataGrid单元格的背景颜色

请问如何让timer控件每过一秒钟触发一次?

定时器触发 Tick 事件,延迟 15 毫秒