skip to Main Content

I have a project that has an update timer that does some background stuff, mainly checking for activity. We need to add some text boxes that have an onChange event. However while typing, the timers event will trigger the textbox.

I thought isolating each in their own updatepanel would help with no success.

The timer event cannot be removed so that’s off the table…I need to take care of the issue on the textbox only. Any suggestions would be appreciated!

Here’s the complete code…basically made a new project as a simple sample since the real project is massive!

<body>
<form id="form1" runat="server">
    <asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
    <asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="conditional" ChildrenAsTriggers="false">
        <Triggers>
            <asp:AsyncPostBackTrigger ControlID="Timer1" EventName="tick" />
        </Triggers>
        <ContentTemplate>
            <asp:Timer ID="Timer1" runat="server" Interval="3000" />
            <div>
                <asp:Label ID="lblTimer" runat="server" Text="0" />
            </div>
        </ContentTemplate>
    </asp:UpdatePanel>

    <asp:UpdatePanel ID="UpdatePanel2" runat="server" UpdateMode="Conditional" ChildrenAsTriggers="false">
        <Triggers>
            <asp:AsyncPostBackTrigger ControlID="TextBox1" EventName="TextChanged" />
        </Triggers>
        <ContentTemplate>
            <div>
                <asp:TextBox ID="TextBox1" runat="server" />
                <asp:Label ID="lblNewText" runat="server" Text="-" />
            </div>
        </ContentTemplate>
    </asp:UpdatePanel>
</form>
Private Sub TextBox1_TextChanged(sender As Object, e As EventArgs) Handles TextBox1.TextChanged
    lblNewText.Text = TextBox1.Text
End Sub

Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
    lblTimer.Text += 1
End Sub

End Class

2

Answers


  1. Chosen as BEST ANSWER

    I'm not sure if it's the best answer, but this is what I've come up with as a quick solution. Basically made up a user control that contains a text box and hidden button. There's a JS onchange event on the textbox that clicks the button, that then raises an event. I'm testing in a few spots now....still dealing with tab index issues but it's not critical.

    front page:

     <%@ Control Language="vb" AutoEventWireup="false" CodeBehind="TextboxUC.ascx.vb" Inherits="Wise.TextboxUC" %>
    <asp:TextBox ID="TextBox1" runat="server" /><asp:Button ID="btnSubmit" runat="server" style="display:none" />
    

    code-behind:

    Public Class TextboxUC
        Inherits System.Web.UI.UserControl
    
        Public Event OnTextChanged As EventHandler
    
        Public Property [text] As String
            Get
                Return TextBox1.Text
            End Get
            Set(value As String)
                TextBox1.Text = value
            End Set
        End Property
    
        Public Property MaxLength As Integer
        Public Property Columns As Integer
    
        Private Sub UCTextbox_Load(sender As Object, e As EventArgs) Handles Me.Load
            If IsPostBack = False Then
                TextBox1.Attributes.Add("onchange", "document.getElementById('" & btnSubmit.ClientID & "').click();")
                If Columns > 0 Then TextBox1.Columns = Columns
                If MaxLength > 0 Then TextBox1.MaxLength = MaxLength
            End If
        End Sub
    
        Private Sub btnSubmit_Click(sender As Object, e As EventArgs) Handles btnSubmit.Click
            TextBox1.Focus()
            RaiseEvent OnTextChanged(ID, e)
        End Sub
    
        Public Overrides Sub Focus()
            TextBox1.Focus()
        End Sub
    End Class
    

  2. You not likely to get this setup working with update panels

    First up, the onchange event for the textbox ONLY triggers when you tab out. So trying to wire up and use the onchange not going to work all that well.

    Next up, if the text box in question suffers a post back (inside a panel or not), then of course the page refresh, and the cursor position is re-set to the start. Thus trying to type into the text box when such post-backs occur not going to work well at all.

    All in all this means that if you going to have a text box that allows typing , and NOT suffer the cursor reset, then the text box really can’t be part of ANY post back, can it?

    Remember, a update panel DOES cause a page life cycle to trigger. And that includes EVERY TIME the code behind page load event runs. So, keep this in mind, since page load does trigger. So, while an update panel gives the illusion of a page post back not occurring, this is NOT THE CASE!

    The correct term for a update panel is what we call a "partial post back". In other words, only the content in the update panel is posted back to the server. However, make no mistake here, it is a full valid page life cycle, and that as noted includes the page load event firing every time (and then say the button code stub runs after page load).

    So, what you could do is say leave the text box outside of the update panel, and then trigger the update panel to run (to say update the label).

    So, this works (I assume jQuery here).

            <asp:TextBox ID="TextBox1" runat="server"
               onkeyup="$('#mybut').click()" />
    
            <asp:UpdatePanel ID="UpdatePanel2" runat="server" UpdateMode="Conditional" >
                <ContentTemplate>
                    <div>
                        <asp:Button ID="mybut" runat="server" Text="Button"  
                            ClientIDMode="Static" OnClick="mybut_Click"  style="display:none" />
    
                        <asp:Label ID="lblNewText" runat="server" Text="-" />
    
                    </div>
                </ContentTemplate>
            </asp:UpdatePanel>
    

    So, for each keystroke in the text box, we used the onkey up (since onchange requires a tab out of the text box for contents of textbox to be seen, and MORE important no tab out of the text box is required).

    Code behind:

    Protected Sub mybut_Click(sender As Object, e As EventArgs)
    
        lblNewText.Text = TextBox1.Text
    
    End Sub
    

    So, above does work, and does allow typing. Since the text box is outside of the update panel, then the post back ONLY includes the content in the update panel, and thus the cursor position of the text box does not change or get messed up.

    Keep in mind that since the text box was OUTSIDE of the update panel, then the control is read only (you can’t change the control in code behind for the udpate panel, but you CAN read the value(s) from controls outside).

    You suggest that the timer is off the table (bad position here, you need some flexibility in your approach here).

    You can have/enjoy the timer UP tick away at the incrementing label value.

    However, for your text box?

    I suggest you adopt JavaScript and client side code. The simple matter is at end of day, if you going to allow typing in the text box, it CAN NOT be posted back and suffer a page life cycle. If the text box does, then as noted, you might as well dump all update panels, since the behaver you see will not be ANY different had you not introduced any update panels in the first place!

    So, the above proof of concept code does allow the label to be changed, and the text box being outside of the panel thus works.

    You are FAR better off to introduce client side JavaScript here. So, while I think a update panel is one of the greatest features of webforms? They don’t really work if you going to try keystroke processing.

    You also don’t mention/note/suggest/hint what your final goal here is?

    For a search as you type text box?

    Well, the internet has boatloads of examples. Many examples using jQuery.UI and "auto complete"

    However, if you have a aversion to writing JavaScript, then you can adopt a nice auto complete utility from the ajaxtoolkit. Adopting the aj toolkit’s auto complate thus results in you not having to write ANY JavaScript (of course the aj toolkit behind the scenes will and does wire up things automatic, and does so doing JavaScript routines that you don’t see nor have to worry about).

    As noted, in above, since the textbox is outside of the UP, then it does not post-back to the server and thus does not get messed up.

    Introduction of say a 2nd update panel with a timer should thus again work fine with the above setup.

    So, we have this:

            <asp:TextBox ID="TextBox1" runat="server"
               onkeyup="$('#mybut').click()" />
    
            <asp:UpdatePanel ID="UpdatePanel2" runat="server" UpdateMode="Conditional" >
                <ContentTemplate>
                    <div>
                        <asp:Button ID="mybut" runat="server" Text="Button"  
                            ClientIDMode="Static" OnClick="mybut_Click"  style="display:none" />
    
                        <asp:Label ID="lblNewText" runat="server" Text="-" />
    
                    </div>
                </ContentTemplate>
            </asp:UpdatePanel>
    
    
            <asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="conditional" >
                <ContentTemplate>
                    <asp:Timer ID="Timer1" runat="server" Interval="1000" />
                    <div>
                        <asp:Label ID="lblTimer" runat="server" Text="0" />
                    </div>
                </ContentTemplate>
            </asp:UpdatePanel>
    

    And thus we see this effect:

    enter image description here

    So, at end of day, you are FAR FAR FAR better off to wire this up using client side JavaScript. The update panels will buy you some real cool abilities, and often eliminate the need for writing and adopting JavaScript and ajax calls to the server code, but as noted, for keystroke processing, they fall down rather hard.

    I think you should outline your goal, and what you trying to accomplish here in place of stomping your feet and stating that you must use a Timer control and update panels. You don’t have to, and to be fair, the issue of a Timer control probably not really much of a issue here anyway.

    The goal so far is the need for keystroke processing in a text box, and that’s something that update panels really can’t help you much with here.

    Edit: User is NOT trying to do keystroke processing

    Ok, so then this is a easy walk in the park in a sense.

    Just remove all your trigger junk in the markup (you do NOT need those triggers).

    So, this then works 100% just fine:

            <asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="conditional">
                <ContentTemplate>
                    <asp:Timer ID="Timer1" runat="server" Interval="1000" />
                    <div>
                        <asp:Label ID="lblTimer" runat="server" Text="0" />
                    </div>
                </ContentTemplate>
            </asp:UpdatePanel>
    
    
    
            <asp:UpdatePanel ID="UpdatePanel2" runat="server" UpdateMode="Conditional">
                <ContentTemplate>
                    <div>
                        <asp:TextBox ID="TextBox1" runat="server"
                            OnTextChanged="TextBox1_TextChanged"
                            AutoPostBack="true">
                        </asp:TextBox>
                        <br />
    
                        <asp:Label ID="lblNewText" runat="server" Text="-" />
    
                    </div>
                </ContentTemplate>
            </asp:UpdatePanel>
    

    And code behind is:

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    
    End Sub
    
    
    Protected Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
        lblTimer.Text += 1
    End Sub
    
    Protected Sub TextBox1_TextChanged(sender As Object, e As EventArgs)
    
        lblNewText.Text = TextBox1.Text
    
    End Sub
    

    And result when run looks like this:

    enter image description here

    Edit 3: textbox is to NOT post back

    Ok, I can make a longer explain, but the post is 100% correct – the textbox is posting back due to the timer update panel (a seperate panel). Giving this some thought, this now makes sense.

    So, I suggest this code for the text box update panel now:

            <asp:UpdatePanel ID="UpdatePanel2" runat="server" UpdateMode="Conditional"
                >
                <ContentTemplate>
                    <div>
                        <asp:TextBox ID="TextBox1" runat="server"
                            onChange="mybutclick()"
                            >
                        </asp:TextBox>
                        <br />
    
                        <asp:Label ID="lblNewText" runat="server" Text="-" />
                        <asp:Button ID="cmdTextChange" 
                            runat="server" Text="change button"
                            ClientIDMode="Static"
                            OnClick="cmdTextChange_Click"                            
                            />
    
                        <script>
                            function mybutclick() {
    
                                $('#cmdTextChange').click()
                            }
    
    
                        </script>
    
                    </div>
                </ContentTemplate>
            </asp:UpdatePanel>
    

    And thus code behind for when the user tabs out of the text box now becomes some button code. Hence this:

    Protected Sub cmdTextChange_Click(sender As Object, e As EventArgs)
    
        Debug.Print("but click - for text change")
        lblNewText.Text = TextBox1.Text
    
    End Sub
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search