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

时间:2014-05-15 09:36:19

标签: asp.net timer textbox updatepanel textchanged

以下代码包含两个更新面板,其中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;
    }

1 个答案:

答案 0 :(得分:0)

我最终理解回发不太适合与页面呈现无关的后台活动。更简洁的方法是调用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" />