【问题标题】:How to make TextBox.TextChanged event to not fire when a Timer triggers its tick?当 Timer 触发其刻度时,如何使 TextBox.TextChanged 事件不触发?
【发布时间】:2014-05-15 09:36:18
【问题描述】:

下面的代码包含两个更新面板,都将UpdateMode 设置为“条件”。一个有一个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;
    }

【问题讨论】:

标签: asp.net timer textbox updatepanel textchanged


【解决方案1】:

我最终了解到回发不太适合与页面渲染无关的后台活动。更简洁的方法是调用 WebService 或发布到不同的页面。扩展 Timer 类,我能够实现第二个策略,覆盖计时器计时时调用的 javascript 函数,使其能够执行到不同 url 的 Post。请随意指出其他行为类似的 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" />

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-20
    • 1970-01-01
    • 2012-09-22
    相关资源
    最近更新 更多