WebForms Textbox.TextChanged event is firing twice on button click - c#

There appears to be a hundred questions that are very similar, but none seem to solve my issue.
I have a very basic bootstrap webform with two textboxes - each accepts a serial number that is populated by a handheld scanner attached to the PC. When the user scans the first barcode, the TextChanged event for txtLabelA fires a method that validates the serial number and switches focus to txtLabelB. When the user scans the second barcode it fires the TextChanged event for txtLabelB. This inserts the two values into a cross reference table in the database, displays a success message and clears the form for the next set of serial numbers. Very straight forward. This has worked flawlessly for a long time.
However, recently I was asked to add a button to the form that allows the user to manually type in a serial number and click Submit. This has now mucked everything up, because clicking the Submit button fires the OnClick AND the OnTextChanged events causing the form to postback twice. How can I prevent this?
<div class="card-body">
<div class="form-group">
<asp:TextBox ID="txtLabelA" runat="server" EnableViewState="true" CssClass="form-control" AutoPostBack="true" OnTextChanged="txtLabelA_TextChanged"></asp:TextBox>
<span class="help-block"></span>
</div>
<div class="form-group">
<asp:TextBox ID="txtLabelB" runat="server" EnableViewState="true" CssClass="form-control" AutoPostBack="true" OnTextChanged="txtLabelB_TextChanged"></asp:TextBox>
<span class="help-block"></span>
</div>
<div class="form-group">
<asp:Button ID="btnSubmit" runat="server" Text="Submit" CssClass="btn btn-primary" OnClick="btnSubmit_Click" />
<asp:Button ID="btnCancel" runat="server" Text="Clear" CssClass="btn btn-secondary" OnClick="btnCancel_Click" />
<div style="margin-top: 10px;">
<p>
<asp:Label ID="lblError" runat="server" CssClass="text-danger"></asp:Label>
<asp:Label ID="lblSuccess" runat="server" CssClass="text-success"></asp:Label>
</p>
</div>
</div>
</div>
Here is a snippet of the code behind (not much to it):
protected void txtLabelA_TextChanged(object sender, EventArgs e)
{
GetLabelDetails();
}
protected void txtLabelB_TextChanged(object sender, EventArgs e)
{
SyncLabels();
}
protected void btnSubmit_Click(object sender, EventArgs e)
{
SyncLabels();
}
I have even tried changing the button's OnClick event to be the OnTextChanged event, but it didn't help.
Does anyone have any thoughts?
Thanks.

Ok folks, we found a solution. I merged the suggestions of both posters above to find a resolution. I started with Daniel's suggestion to put nothing in the button's click event to ensure it would not trigger the SyncLabels() method, but that alone did not completely solve it because the event itself was still causing a postback. The trick was including Bmils' note above to add a meaningless javascript function to the OnClientCLick() event of the button. This allowed me to "return: false;", effectively blocking the second postback on the client side. Thank you both for your input. I wouldn't have resolved this with your help.

https://learn.microsoft.com/en-us/dotnet/api/system.web.ui.webcontrols.textbox.autopostback?view=netframework-4.8
Use the AutoPostBack property to specify whether an automatic postback to the server will occur when the TextBox control loses focus. Pressing the ENTER or the TAB key while in the TextBox control is the most common way to change focus.
In my personal experience, barcode scanners essentially mimic a user typing in a barcode number and then pressing ENTER. If a user manually types in a barcode number and then clicks on the Submit button, then the TextBox is losing focus anyway and causing the additional Postback.
Recommendation: Remove the Button.Click event (or at least the logic within the Click handler.)
Note: If the TextBox control's parent container contains a button marked as the default button (for example, if the container's DefaultButton or DefaultButton property is set), the default button's Click event is not raised in response to the automatic postback.

Related

Why is there no PostBack for a form on a UserControl?

I have a problem understanding where I am losing the ability to catch the PostBack trigger or simply the handler method of serverclick in this setup and placing breakpoints only shows the PostBack occurs on rendering (Page_Load) but not after submit button is clicked. Allow me to elaborate on the scenario and keep in mind I have limited ability to change the way it is done and must figure out a way to make it work with minor changes using ASP.net / C# / WebForms / Bootstrap 4.5 per the client.
Dashboard.aspx [main page] has a simple (top nav showing the logo and logged in user's name with a signout drop down, sidebar menu which upon individual click will load into a display area) and the display area is an asp:PlaceHolder element:
<asp:PlaceHolder runat="server" ClientIDMode="Static" ID="TheScreen">
When the [main page] is loaded, it makes an API call and processes a collection of objects received and generates adding a series of UserControl Control1 objects (this can be zero items or n items) let's call this [default state] of the landing so we can refer to it later.
Each of the Control1 (which have unique IDs) have 3 buttons to perform 3 different actions.
<a class="btn btn-primary btn-sm" id="action1" runat="server" onserverclick="Command_Click">Do First Action</a>
<a class="btn btn-primary btn-sm" id="action2" runat="server" onserverclick="Command_Click">Do Second Action</a>
<a class="btn btn-primary btn-sm" id="action3" runat="server" onserverclick="Command_Click">Do Third Action</a>
Command_Click simply bubbles up an event handler to be processed by Dashboard.aspx
public void Command_Click(object sender, EventArgs e)
{
CommandClicked?.Invoke(sender, e);
}
action1 is handled on the fly with a confirmation modal which contains a simple button that runs onserverclick and reloads the [default state] having deleted that item using an API call.
<button type="button" class="btn" id="do-action1" runat="server" onserverclick="finish-action1">Do It</button>
This all works as expected.
action2 is handled by [main page] where it clears the PlaceHolder's controls and then dynamically creates and loads another UserControl which displays long form details of that object.
UControl2 theObject = (UControl2)Page.LoadControl("~/path/to/Control2.ascx");
TheScreen.Controls.Clear();
TheScreen.Controls.Add(theObject);
This all works as expected also.
action3 button is the one that is giving me the problem and just like action2 it is handled on [main page] where it clears the PlaceHolder's controls and then dynamically creates and loads another UserControl which provide a simple form with one button on it.
UControl3 otherObject = (UControl3)Page.LoadControl("~/path/to/Control3.ascx");
TheScreen.Controls.Clear();
TheScreen.Controls.Add(otherObject);
The form is very simple, contains a <select> elements whose <option> are populated using an asp:Repeater based on an API call that provides the DataSource for it. It also has a simple <input> textbox field and lastly a submit <button>.
<select id="..." name="..." required="required">
<option disabled selected value="">select payment account</option>
<asp:Repeater ID="..." ClientIDMode="Static" runat="server" ItemType="model.namespace">
<ItemTemplate>
<option value="<%#: Eval("...") %>">
<%#: Eval("...") + " " + Eval("...") %>
</option>
</ItemTemplate>
</asp:Repeater>
</select>
<input id="..." name="..." type="text" required="required" runat="server" />
<button id="finish-action3" class="btn" runat="server" onserverclick="do-action3">Do It</button>
What I don't get is why finish-action3 is not performing the actions of the handler method do-action3, it simply refreshes back to the [main page] with the initial state that we started from with the initial Control1s being rendered and nothing else, no PostBack either.
I have searched extensively and found nothing addressing this specific scenario and what I have found, everyone keeps suggesting using asp:Button but that makes no difference for me in the behavior.
As written above, clicking finish-action3 button which is part of Control3 will not cause the basic HTML5 validation and does not trigger the do-action3 handler method and simply refreshes back to the [main page] where we started.
If I add do-action3 to the onsubmit attribute OR add type=submit, I get the validation but once it passes validation, the same behavior, nothing but load the [main page].
Changing the element to an asp:Button made absolutely no difference. The validation is triggered without anything special (like using onsubmit attribute or having a type=submit but once it is validated the same behavior, never calls do-action3 nor does it even trigger a Page_Load/PostBack on control3 just back to the [main page].
I suspect I am overlooking some event or is not bubbling and is getting lost in the process but I can't think what it is and where and why. Why doesn't the form that is last on the screen loaded by Control3 "submitted" by that button click not generating a PostBack or running the onserverclick handler method and simply refreshing to the main default state page, what am I missing here?
Any help would be appreciated as I have been banging my head against the wall trying to figure out what I am missing. I never encountered this in MVC or Core and it is making me crazy.
Let's simplify. Basically, what you are saying is that the following does not work because the btnFinishAction3_Click method of the dynamically-added Control3 user control is not firing:
Default.aspx (main page):
<asp:PlaceHolder runat="server" ID="plhPlaceHolder1"></asp:PlaceHolder>
<asp:Button runat="server" ID="btnAction3"
Text="Do Third Action"
OnClick="btnAction3_Click"/>
Default.aspx.cs:
protected void btnAction3_Click(object sender, EventArgs e)
{
AddControl3();
}
private void AddControl3()
{
Control3 objControl3 = (Control3)Page.LoadControl("~/Control3.ascx");
plhPlaceHolder1.Controls.Clear();
plhPlaceHolder1.Controls.Add(objControl3);
}
Control3.ascx:
<asp:Label runat="server" ID="lblMessage"></asp:Label>
<asp:Button runat="server" ID="btnFinishAction3"
Text="Finish Action 3"
OnClick="btnFinishAction3_Click"/>
Control3.ascx.cs:
protected void btnFinishAction3_Click(object sender, EventArgs e)
{
lblMessage.Text = "Finished Action 3.";
}
This is normal behavior. After postback the dynamically added user control does not exist and the event is "ignored". In ASP.NET Web Forms, every dynamic control must be re-added to the page after every postback. So, you need something like the following:
Default.aspx (main page):
<asp:PlaceHolder runat="server" ID="plhPlaceHolder1"></asp:PlaceHolder>
<asp:HiddenField runat="server" ID="hifControl3Loaded"/>
<asp:Button runat="server" ID="btnAction3"
Text="Do Third Action"
OnClick="btnAction3_Click"/>
Default.aspx.cs:
protected void Page_Load(object sender, EventArgs e)
{
if (hifControl3Loaded.Value == "1")
{
AddControl3();
}
}
protected void btnAction3_Click(object sender, EventArgs e)
{
AddControl3();
hifControl3Loaded.Value = "1";
}
private void AddControl3()
{
Control3 objControl3 = (Control3)Page.LoadControl("~/Control3.ascx");
plhPlaceHolder1.Controls.Clear();
plhPlaceHolder1.Controls.Add(objControl3);
}
In other words, you need to add Control3 to the main page at every postback on Page_Load once the user has decided to add it by clicking the btnAction3 button in the first place.

"How to Prevent multiple events C#?"

I have textbox control with auto postback = "true" in update panel and there is save button with access key of "Alt + s" when i change something into textbox and without losing focus if user has pressed "Alt + s" than need to call first text change event of textbox and then should fire save click event once as there is some calculation on text change event.In this situation first it fires text change event than it call save click event and than it calls again text change event.
Is there any good approach to resolve issue either client side or server side or from sql side?
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:TextBox ID="Txt_Val" runat="server" AutoPostBack="True"
OnTextChanged="Txt_Val_TextChanged"></asp:TextBox>
<asp:Button ID="Btn_Save" runat="server" OnClick="Btn_Save_Click"
Text="Save" AccessKey="S" ValidationGroup="S"/>
</ContentTemplate>
</asp:UpdatePanel>
protected void Btn_Save_Click(object sender, EventArgs e)
{
//Save data into database
}
protected void Txt_Val_TextChanged(object sender, EventArgs e)
{
// Some calculation
}
Solution 1 :
Here the Microsoft provide the Control.Update Method documentation here https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.control.update?view=netframework-4.8. its last update value store in Database.
Solution 2 :
please check your event its some another event call then sometimes this issue is given.
Solution 3 :
you Set focus after a update a value in the page load event
protected void Page_Load(object sender, EventArgs e)
{
TextBox1.Focus();
}
second time set focus and after update is a 3rd solution for this issue.
I hope the above three solutions is helpful.
when i change something into textbox and without losing focus if user has pressed "Alt + s" than need to call first text change event of textbox and then should fire save click event once as there is some calculation on text change event
quoted statement can also be handled like this:
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:TextBox ID="Txt_Val" runat="server" AutoPostBack="True"
OnTextChanged="Txt_Val_TextChanged"></asp:TextBox>
<asp:Button ID="Btn_Save" runat="server" OnClick="Btn_Save_Click"
Text="Save" AccessKey="S" ValidationGroup="S" OnClientClick="return verifyFirst();" />
</ContentTemplate>
</asp:UpdatePanel>
<script>
function verifyFirst(){
return verifyChangedText($('[id$=Txt_Val]'));
}
function verifyChangedText(elem){
//verify your stuff on client level.
//if you need to do the server side stuff, hit WebMethod using ajax
//finally according to the result
if(everythingIsOk){
return true;
}
return false;
}
</script>
onClientClick executes first on client side, if everything is satisfactory the return bool value if true it executes the server side event call OnClick="Btn_Save_Click" and if its false then it doesn't execute the server side event call.
UPDATED
I have multiple textboxes with text change event on page or in grid for each text box control it will be difficult to handle
as per your comment quoted above, you can handle multiple TextBox verification
but it can only be handled in following manner:
if a user presses enter without focusing out then we don't know on which TextBox user made changes to so we will have to check all the TextBoxes present in the form and fire each TextBox's onkeypress event.
for e.g:
i = 0;
function verifyMe(event,args){
debugger;
$(args).text(i += 1);
};
function verifyThisStuff(){
var e = jQuery.Event("keypress");
$('.forVerification').each(function(){
$(this).trigger(e);
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="text" class="forVerification" onkeypress="return verifyMe(event,'#span1');">
<input type="text" class="forVerification" onkeypress="return verifyMe(event,'#span2');">
<button type="button" onclick="return verifyThisStuff();">click Me</button>
<p>textbox 1 Keypresses: <span id="span1">0</span></p>
<p>textbox 2 Keypresses: <span id="span2">0</span></p>

asp RadioButton not selected when Checked="true"

I have two radio buttons "Yes" and "No" and I want the "No" radio button to be selected by default. However, I can't get it be be selected through the asp code or by the code behind. Am I doing this completely wrong or did I just miss something.
ASP code:
<div class="query_header" runat="server" id="ScanOnStartup">
<div class="formlabel" style="width: 300px">Perform Scan on startup</div>
<div class="formfield" style="line-height: 10px">
<asp:RadioButton ID="scanOnStartupYes" Text="Yes" GroupName="ScanOnStartupRadio" runat="server" AutoPostBack="false" Checked="false"/>&nbsp
<asp:RadioButton ID="sanOnStartupNo" Text="No" GroupName="ScanOnStartupRadio" runat="server" AutoPostBack="false" Checked="true"/>
</div>
<div class="formdivider"></div>
</div>
Code behind:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
this.scanOnStartupNo.Checked = true;
}
If you need to make a radio button checked by default on page load , you can do one of the above
From the front end , you can add the property
Checked="checked"
From the code behind, you can write it as
scanOnStartupNo.Checked=true
When I checked your code , You have made a spelling mistake in declaring the ID of NO button. That was why the code behind code piece was not working
Okay aside from the typo "sanOnStartupNo", I know where the problem is coming from. There was actually another control from my code behind that renders the page and that is where the selection for the radio button is being set. I added in code for my radio button and it works now.

OnClick Event not firing when I am specifying action url in asp.net

I need to redirect the user to paypal account. But before that I want to collect name and email for that user. So I am using the following code.
<form id="paypalForm" method="post" action="https://www.paypal.com/cgi-bin/webscr"
target="_top" runat="server">
<div>
<label>
Full Name:<span>*</span></label>
<asp:TextBox ID="name" runat="server" CssClass="large form-poshytip" title="Enter your Full Name."></asp:TextBox>
<label>
E-Mail:<span>*</span></label>
<asp:TextBox ID="email" runat="server" CssClass="large form-poshytip" title="Enter Email Address."></asp:TextBox>
<input type="hidden" name="cmd" value="_s-xclick" />
<div id="partnerFormButton">
<br />
<asp:ImageButton runat="server" Name="btnSubmit" Text=" Next "
ID="btnSubmit"
ImageUrl="https://www.paypalobjects.com/en_GB/i/btn/btn_buynowCC_LG.gif"
onclick="btnSubmit_Click" CausesValidation="False" ></asp:ImageButton>
</div>
</div>
</form>
Code Behind code:
protected void btnSubmit_Click(object sender, ImageClickEventArgs e)
{
//some code
}
But the problem is that OnClick event doesn't firing and it redirects to the specified action url.
What can be the problem?
Thank you so much in advance...!!
It's not how ASP.NET events work. Events are fired after postback is made and you are preventing the postback by submitting the form. You need to decide what to do - either submit data with the form (like what you are doing now) and not use OnClick event or use the event and remove action and method parameters from form.
http://msdn.microsoft.com/en-us/library/ms178472.aspx
To explain it further: an event will not fire right after you click the button. What happens is that a POST request is being made to the same page with the page state passed in the ViewState. In other words - pressing the button in ASP.NET by default works kind of like a link to the same page (it's a veeeery simplified explanation though). Events are fired only after that request is made and after the page is loaded again - see the link above.
What you are doing right now is forcing the request to go to another page. Even though the button 'wants' to do a postback, the action parameter in your <form> points the request somewhere else. Since the postback isn't made and your page isn't loaded again, the event will not fire.
IISTe Technologies is going to introduce a blog for their student and other developers where they can find and share their problem and solution regarding c, c++, .NET java, PHP and others, here you one can find the exact solution of their programming problems.
Basically you have specified the action in the form tag.
You can redirect the page to "https://www.paypal.com/cgi-bin/webscr" in the click event. For if u specif action then you you wont be able to sumbit the data of the for. You won't get the values.
It will never go to the click event code block you have written. Because you are posting the page to paypal page instead of self.
Try this:
Remove action attribute from form.
Write click event as
protected void btnSubmit_Click(object sender, ImageClickEventArgs e)
{
var target = #"https://www.paypal.com/cgi-bin/webscr";
Response.Status = "307 Temporary Redirect";
Response.AddHeader("Location", target);
}

Method being triggered on page load but not via asp button

I have two asp:Labels, the first of which is replaced with a few buttons and the second with a list of items.
I want to click on the buttons to filter the items.
The contents of the buttons are added programmatically by replacing the text with html and works fine.
asp:
<form id="form1" runat="server">
<asp:Label id="filters" runat="server" Text="Filters here"/>
<asp:Label id="itemList" runat="server" Text="List of items here"/>
</form>
resultant html of filters label:
<input type="submit" onclientclick="Load_Items(0)" runat="server" value="First"/>
<input type="submit" onclientclick="Load_Items(1)" runat="server" value="Second"/>
<input type="submit" onclientclick="Load_Items(2)" runat="server" value="Third"/>
relevant c#:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
Load_Items(0);
}
}
public void Load_Items(int filterType)
{
//code to load items (pseudo below)
for each row in list
if filterType = itemType
build string
replace second label with string
}
On page load everything happens just as I want it to with the contents being filtered by the first item (hence Load_Items(0)), and if I manually change the 0 to another number in Page_Load, it filters by the other types, but if I click the buttons which are programmatically added, nothing happens other than what looks like the page refreshing.
I know the post back check is working by adding a text replacement before and inside it.
I've also added an asp:button to make sure it's not something to do with the way the buttons are added as below (with some extra things recommended from searches):
<asp:Button runat="server" CausesValidation="False" onclientclick="Load_Items(2); return false;" text="Submit" />
So what could be the issue?
The OnClientClick property specifies the javascript to run in the browser when the button is clicked. Since you probably don't have a javascript function called Load_Items, this will generate a script error, and the button will then cause the form to post back.
The server-side Click event will fire on the server, but doesn't allow you to pass a parameter. You will only get the button instance and an empty EventArgs instance.
You might be better off using the Command event, combined with the CommandArgument property.
<asp:Button runat="server" CommandArgument="2" OnCommand="Load_Items" ...
The event handler would use the CommandArgument property of the CommandEventArgs to access the argument from the clicked button:
protected void Load_Items(object sender, CommandEventArgs e)
{
Load_Items(Convert.ToInt32(e.CommandArgument));
}
Well, that's the common problem which I think every asp.net developer deals some time. The common part of it, that asp.net event system doesn't work, as windows forms.
Page object, and all controls on that page, have lifecycle events, that are triggered during any request, even when it's from update panel.
As you create those controls by code, you have to keep in mind, that all events for those controls should work as part of Page object. That's why you have to create those object in Page_Init event, before all other control's event would be triggered.
Please also keep in mind that you have to create those controls as asp.net objects:
var btn = new Button();
But not by simply adding html markup. And you have to recreate them on each request, following that one, when they were created.
Please take a look on my another answer.

Categories