Server Transfer with preserveForm true in EventHandler refires that event Handler and causes infinite loop.
MY QUESTION: How can I indicate in the handler that the event has been handled.
PS: I know we can set the preserveForm to false, but I dont want to do that.
Sample Code:
protected void rbThemes_SelectedIndexChanged(object sender, EventArgs e)
{
Server.Transfer(Request.FilePath, true);
}
Great question that I'm facing right now. I don't know the answer either, I would imagine one would modify Request.Form data to remove the event, though I'm not sure how to do this cleanly.
As a workaround, I use a guard flag in Context.Items, which is preserved as well.
protected void rbThemes_SelectedIndexChanged(object sender, EventArgs e)
{
if (IsSecondPass()) return;
Server.Transfer(Request.FilePath, true);
}
private bool IsSecondPass()
{
const string key = "SECOND_PASS_GUARD";
if (Context.Items[key] == null)
{
Context.Items[key] = new object();
return false;
}
else
{
Context.Items.Remove(key);
return true;
}
}
I wouldn't recommend this, but it works. (Method name is also very poorly chosen as it side-effects.)
There's also a shorter way:
protected void rbThemes_SelectedIndexChanged(object sender, EventArgs e)
{
if (PreviousPage != null) return;
Server.Transfer(Request.FilePath, true);
}
Beware that it doesn't have any undesired effects if you do other kinds of cross-page postings (though I don't know why or how you would cross-post a SelectedIndexChanged event from another page). Still not recommended.
Note: If you're coding a master page, you'll need to reference PreviousPage from the Page property on the master page class (Page.PreviousPage).
Related
I have a method like this:
private async void BtnGivePermit_Click(object sender, EventArgs e)
{
//some code here
}
And I'm trying to add a button to Cancel and in there I wanted to check if any other click event is not in progress. How can I do that in C#?
As Ash suggested, you may want to have a boolean like so:
bool isGivePermitProcessing = false;
private void BtnGivePermit_Click(object sender, EventArgs e)
{
isGivePermitProcessing = true;
try {
...
} finally {
isGivePermitProcessing = false;
}
}
This will give you a definite understanding of whether the function is currently processing or not.
The try-finally block ensures that no exception will cause the isGivePermitProcessing boolean to become indefinitely true.
Extending the above concept into Jimi's suggestion, you could also simply disable the button like so:
private void BtnGivePermit_Click(object sender, EventArgs e)
{
BtnGivePermit.Enabled = false;
try {
...
} finally {
BtnGivePermit.Enabled = true;
}
}
This will also give you a definite understanding of whether the function is currently processing or not while additionally preventing the button from being clicked while already processing a previous click.
If you're intending to make a cancel button for asynchronous operations, you might want to look into the CancellationToken type.
Let me elaborate on this... I have the code below, there is a Page_Init (which I still don't understand why it fires more than once, but that is another story), and a Page_Load and I am checking for the "isPostBack" ... everything works great while I use my controls, radio button and drop down list, as well as Buttons; however, if I press the key, even accidentally, the "isPostBack" is reset to False. What am I doing wrong? Also, my AutoEventWireup="true".
Also, this is an .ascx file.
protected void Page_init(object sender, EventArgs e)
{
LoadPageText1();
paymntpnl1.Visible = true;
curbalpnl.Visible = false;
paymntpnl2.Visible = false;
paymntpnl3.Visible = false;
paymntpnlcc.Visible = false;
}
protected void Page_Load(object sender, EventArgs e)
{
LoadPageData();
getContractInfo();
step2lbl.BackColor = System.Drawing.Color.White;
nopmt = Convert.ToDecimal(numpmts.Text);
nopmt = nopmt * nopymts2;
sb.Clear();
sb.Append("$");
sb.Append(nopmt.ToString("#.00"));
nopymts.Text = sb.ToString();
ValidateCC();
chkNewCC();
bool crdcrd = credCard;
bool newcrd = nwCard;
if (!IsPostBack){
}
}
You're checking IsPostBack but you're still doing all the resetting before the check! And then the check makes no difference because it's an empty conditional block! You should be doing this:
protected void Page_Load(object sender, EventArgs e)
{
if(!IsPostBack)
{
// All the initial setup that you don't want to do again goes here.
}
// All the stuff you want to do on first load AND PostBack goes here.
}
Make sure you understand how conditionals work.
As mentioned above,
How can I disable (or some workaround programatically) this?
some pseudocode could be:
cellvaluechangedevent/rowaddedevent(sender,e){
If(initial load of datagrid){
//trap this, end of method
}
else{
//do work
}
}
I tend to separate my data loading into its own method. As such, I can then detach handlers which may be fired during a load or refresh, and then simply re-attach when that process is finished. This also makes it easier (where applicable) to refresh the dgv data from other places in the code.
The key, in the context of your problem, is:
detach handler
fill DataGridView or attach data source, however you are doing that.
re-attach handler
private void LoadDataGrid()
{
this.dataGridView1.CellValueChanged -= new
DataGridViewCellEventHandler(dataGridView1_CellValueChanged);
// Your code to load data here
this.dataGridView1.CellValueChanged +=new
DataGridViewCellEventHandler(dataGridView1_CellValueChanged);
}
void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
// Your code to handle the cell value changing
}
Seems you just want to bypass the first time it fired.
Assume your DataGridView named dataGridView1, and assigned the original handler dataGridView1_CellValueChanged, then you can do:
private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e) {
dataGridView1.CellValueChanged-=dataGridView1_CellValueChanged;
dataGridView1.CellValueChanged+=
(sender_, e_) => {
MessageBox.Show("fired after first time");
};
}
You can use DataGridView.IsCurrentCellDirty or IsCurrentRowDirty
cellvaluechangedevent/rowaddedevent(sender,e){
if (dataGridView1.IsCurrentCellDirty) {
If(initial load of datagrid){
//trap this, end of method
}
else{
//do work
}
}
}
am wondering why this code fails to focus the textbox...?
private void sendEmail_btn_Click(object sender, EventArgs e)
{
String sendTo = recipientEmail_tbx.Text.Trim();
if (!IsValidEmailAddress(sendTo))
{
MessageBox.Show("Please Enter valid Email address","Cognex" MessageBoxButtons.OK, MessageBoxIcon.Error);
recipientEmail_tbx.Focus();
}
}
Use Select() instead:
recipientEmail_tbx.Select();
Focus is a low-level method intended primarily for custom control authors. Instead, application programmers should use the Select method or the ActiveControl property for child controls, or the Activate method for forms.
http://msdn.microsoft.com/en-us/library/system.windows.forms.control.focus.aspx
Add Delay some miliSec. Delay then call Focus() and Not forget to put inside Dispatcher.
Task.Delay(100).ContinueWith(_ =>
{
Application.Current.Dispatcher.Invoke(new Action(() =>
{
TextBoxNAme.Focus();
}));
});
Even I tried with lots of above solutions but none of them worked for me as am trying to focus on page load. Finally I got this solution and it worked.
private void txtBox_LayoutUpdated(object sender, EventArgs e)
{
txtBox.Focus();
}
Use the Form_Activated event handler, in conjunction with a firstActivation boolean.
private bool firstActivation = true;
private Control firstWindowsControl = null;
...
private void DynamicForm_Activated(object sender, EventArgs e)
{
if (firstActivation)
{
firstActivation = false;
bool fwcPresent = (firstWindowsControl != null);
Console.WriteLine($"DynamicForm_Activated: firstWindowControl present: {fwcPresent}");
if (fwcPresent)
{
firstWindowsControl.Focus();
}
}
I have a problem with a webform.
My Goal: Intially when a page is loading, it has to load every textbox empty. After filling the info and click submit, it has to get submitted(UpdatePaymentInfo())
Problem: Here, When the user fills the info and clicks Submit,it calls onload function even before the submit button and makes all text box empty.
Here is the code:
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
string QueryStringupdatecreditcard1 = Request.QueryString.ToString();
if (String.Equals(QueryStringupdatecreditcard1, "tabID=B"))
{
divTitle.Visible = false;
trmain.Visible = false;
tdOrderSummary.Visible = false;
trCCandBilling.Visible = true;
trtest2.Visible = false;
divUpdatecreditcard.Visible = true;
trusecompaddress.Visible = false;
txtFirstName.Text = "";
txtLastName.Text = "";
txtAddress1.Text = "";
txtAddress2.Text = "";
txtCity.Text = "";
txtZip.Text = "";
txtCardNo.Text = "";
txtVccNumber.Text = "";
trAmountCharged.Visible = false;
}
}
protected void imgbtnSubmit_Click(object sender, ImageClickEventArgs e)
{
try
{
UpdatePaymentInfo();
}
}
Wrap the current contents of your OnLoad method in:
if (!Page.IsPostBack)
{
// Code in here will only be executed when the page is *not* being loaded by a postback
}
This is because, as per the ASP.NET Page Life Cyle, the things that you care about in this instance happen in this order:
Load - During load, if the current request is a postback, control
properties are loaded with information
recovered from view state and control
state.
Postback event handling - If the request is a postback, control event
handlers are called. After that, the
Validate method of all validator
controls is called, which sets the
IsValid property of individual
validator controls and of the page.
So what happens is (somewhat simplified):
You click the image button, triggering the postback.
The data from your form is loaded into your controls.
Your OnLoad method overwrites the values in the controls to clear them.
Your click handler is run, but because of step 3 it sees empty values.
As others have sort-of mentioned, it wouldn't necessarily be a bad thing to refactor your OnLoad method whilst you're doing this. At the moment you seem to have it doing two distinct things:
Clearing the text fields
Setting the visibility of fields
It might be worth separating this into one or two (depending on if the visibility setting and field clearing will be done independently) separate methods and adjusting your OnLoad method so it looks like this:
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if (!Page.IsInPostBack)
{
SetFieldVisibility();
ClearFields();
}
}
Page_Load always occurs.
See the documentation on the Page Lifecycle
What you need to do is check to see if the Page_Load is being triggered by a Postback.
private void Page_Load(object sender, System.EventArgs e)
{
if(!Page.IsPostBack)
{
///do stuff in here that you want to occur only on the first lad.
}
else
}
// code that you want to execute only if this IS a postback here.
{
}
// do stuff you want to do on Page_Load regardless of postback here.
}
You can use the IsPostBack property of the Page as follows:
protected override void OnLoad(EventArgs e) {
if (!Page.IsPostBack) {
EmptyTextBoxes();
}
}
Have you tried wrapping the form reset code in a check to see if the page is a postback?
if(!Page.IsPostback) {
// Do form reset here
}
You thought about using the IsPostBack page variable?
protected override void OnLoad(EventArgs e)
{
if(!IsPostBack){
//all your logic here.
}
}
if it's the case, you might use a databound control and set it to insert mode