static bool is always true - c#

I have a web form application that looks like such.
public partial class MyPage : Page
{
private static bool _changed = false;
protected void btnSave_Click(object sender, EventArgs e)
{
if(_changed)
{
//some code here
}
}
protected void btnCancel_Click(object sender, EventArgs e)
{
Response.Redirect("~/MyPage.aspx");
}
protected void dropdownlist_SelectedIndexChanged(object sender, EventArgs e)
{
_changed = true;
}
}
So the gist of what I'm trying to do is that I have a form, which contains a drop down list and a save button. If the user makes a change to the drop down list, I set the private boolean changed to be true. By default, it is false.
For some reason that I do not understand, changed is true when it gets to the btnSave_click method even though it never visited the dropdownlist_selectedIndexChanged method, which is the only place in my code that sets changed to be true.
The markup:
<asp:DropDownList ID="myDropDown" runat=server" OnSelectedIndexChanged="dropdownlist_SelectedIndexChanged" AutoPostBack="true">
<asp:ListItem Value="True">Yes</asp:ListItem>
<asp:ListItem Value="False">No</asp:ListItem>
<asp:Button ID="btnSave" Text="Save" OnClick="btnSave_Click" runat="server" />

Are you really sure that you want to use a static field variable which is shared across all requests? So when UserA selects something in the DropDown, UserB will also have _changed = true.
You might want to use a ViewState or Session variable instead, e.g.:
private bool HasChanged
{
get { object b = ViewState["HasChanged"] ?? false; return (bool)b; }
set { ViewState["HasChanged"] = value; }
}
Nine Options for Managing Persistent User State in Your ASP.NET Application

I think the SelectedIndexChanged gets triggered by the <select> element getting populated with it's initial values. This means that while your form is initializing, before the user can even interact with it, your dropdownlist_SelectedIndexChanged() method is being invoked. You can verify this by using a debugger to see when this method is being executed.
Also, as others have mentioned, a static member is nto a good idea to store request variables; ViewState is better suited for this.
UPDATE
I think the SelectedIndexChanged gets triggered by the <select> element getting populated with it's initial values.
This is not true.
I tested this out with a very simple web-app and the SelectedIndexChanged event does not get fired when initial values are being added to the DropDownList through the declarative file (MyPage.aspx).
I even tried to change the SelectedIndex programmatically in the code behind.
protected void Page_Load(object sender, EventArgs e)
{
myDropDownList.Items.Add(new ListItem("Text", "Value"));
myDropDownList.SelectedIndex = 2;
}
Still, even when doing this, the myDropDownList_SelectedIndexChanged event does not get fired until changing the selected item through interacting with the webpage.

Related

Why doesn't asp.net button work?

I have used this behind asp button click function. It works on local system but not after begin deployed on server. Why ?
public void EmployeeDeActivation()
{
hdnfieldSessionPersonalInfoID.Value = "0";
Session["ExtraPersonalInfoID"] = 0;
Response.Redirect("EmployeeInformation.aspx", false);
}
.aspx code:
<asp:Button ID="btnEmployeeActivated" runat="server" Visible="false" OnClick="btnEmployeeActivated_Click"
CssClass="btn btn-rounded pull-right btnEmployeeActivated" />
i.e. when i click button when on local system, it hits then button event and refrehes the page but when it doesn't work like then button click never hits.
Update:
protected void btnEmployeeActivated_Click(object sender, EventArgs e)
{
try
{
EmployeeDeActivation();
}
catch (Exception ex)
{
throw;
}
}
Doesn't this method need to accept an event handler? E.g.
protected virtual void OnClick(
EventArgs e
)
Also, the part of code where you set your hidden is not needed as you redirect after.
Also it has the wrong name as it doesn't match the onclick name
Try to enable Trace and log on every method in the page. Try to visualize what your code is doing during postback.
Another useful tool is Glimpse.
Hope it helps!
asp button property "Visible" is set to false in your code. how come button is rendering at first place ?

Passing session variable from page to page

I'm wondering what is my issue on passing a variable from page to page using asp.net session.
I've stripped the code down to just one text box to see whats going on. I'm just trying to take the value of a text box and display it on a confirmation page. When the button is clicked it transfers me to the second page but there label is blank. Yes my post back url is pointing to the second page.
Here is the button click:
protected void submit_Click(object sender, EventArgs e)
{
string name = txtFirstName.Text.Trim();
Session["name"] = name;
}
Here is the page load of the second page:
protected void Page_Load(object sender, EventArgs e)
{
lblName.Text = (string)(Session["name"]);
}
Unless I've been looking at this to long and missed something. I've already read "How to: Read Values from Session State" from MSDN.
You say that you've set the PostBackUrl to your second page. If you're going to do it that way, you need to use Page.PreviousPage to get access to your textbox. But this is the easiest way:
Firstly, leave the PostBackUrl alone. Setting the PostBackUrl to your second page means that you're telling the SECOND PAGE to handle your button click, not the first page. Hence, your session variable never gets set, and is null when you try to pull it.
This should work for ya.
And yes, you can also do this with a QueryString, but if its something that you don't want the user to see/edit, then a Session variable is better.
protected void submit_Click(object sender, EventArgs e)
{
string name = txtFirstName.Text.Trim();
Session["name"] = name;
Response.Redirect("PageTwo.aspx");
}
Then in the second page (You don't REALLY need the ToString()):
protected void Page_Load(object sender, EventArgs e)
{
if (Session["name"] != null)
{
lblName.Text = Session["name"].ToString();
}
}
EDIT -- Make sure that your button click actually gets fired. Someone can correct me wrong on this, as I do most of my work in VB.NET, not C#. But if you don't specify the OnClick value, your function won't get called.
<asp:Button ID="Button1" runat="server" Text="Click Me!" OnClick="submit_Click" />
The code you have posted looks fine, so your problem is probably with setup.
Check this link ASP.NET Session State Overview and pay particular attention to the sections on Cookieless SessionIDs and Configuring Session State.
I don't think you added the session. This is how I have done mine.
First Page
protected void btnView_Click(object sender, EventArgs e)
{
foreach (ListItem li in lbxCheckDates.Items)
{
if (li.Selected == true)
{
lblMessage.Text = "";
string checkDate = lbxCheckDates.SelectedItem.Text;
Session.Add("CheckDates", checkDate);
Page.ClientScript.RegisterStartupScript(
this.GetType(), "OpenWindow", "window.open('Paystub.aspx','_newtab');", true);
}
}
}
Second Page
protected void Page_Load(object sender, EventArgs e)
{
string checkDate = (string)(Session["CheckDates"]);
//I use checkDate in sql to populate a report viewer
}
So with yours, I think you need..
protected void submit_Click(object sender, EventArgs e)
{
string name = txtFirstName.Text.Trim();
Session.Add("Name", name);
}
I think what you have in the second page should work, but if it doesn't, add ToString() to it like..
lblName.Text = (string)(Session["name"]).ToString();
Let me know if this helps!
Are you doing a redirect after setting the session variable on the first page, if so you it will not work correctly (unless you know the trick). Checkout this article on making it work. Basically, the way to make this work is to the overload redirect method.
Response.Redirect("~/newpage.aspx", false);
The false parameter prevents .net from terminate processing on the existing page (that actually writes out the session state)
For Second Page
protected void Page_Load(object sender, EventArgs e)
{
if (Session["value"] != null)
{
Label1.Text = Session["value"].ToString();
}
else
{
Label1.Text = "Sorry,Please enter the value ";
}
}
You can use Server.Transfer() instead of Response.Redirect()
For first page, use this:
protected void Button1_Click(object sender, EventArgs e)
{
string value = TextBox1.Text;
Session["value"] = value;
Response.Redirect("~/Sessionpage.aspx");
}

ASP.NET DropDownList SelectedIndex not changing on first element

I used to think my c# programming wasn't too bad, but today I am seriously questioning my head, something so small is defeating me...
I am trying to get a DropDownList to behave but we are not getting on today. I have a simple DropDownList in an ascx control which is dynamically loaded into an aspx page
<asp:DropDownList ID="ddl_SortBy" runat="server" AutoPostBack="true">
<asp:ListItem Value="0">Sort Alphabetically A to Z</asp:ListItem>
<asp:ListItem Value="1">Sort Alphabetically Z to A</asp:ListItem>
</asp:DropDownList>
and some code behind..
private short SortBy = 0;
protected void Page_Load(object sender, EventArgs e)
{
this.ddl_SortBy.SelectedIndex = -1;
this.ddl_SortBy.SelectedIndexChanged += new EventHandler(ddl_SortBy_SelectedIndexChanged);
if (!IsPostBack)
SearchDirectory();
}
public void ddl_SortBy_SelectedIndexChanged(object sender, EventArgs e)
{
SortBy = Convert.ToInt16(this.ddl_SortBy.SelectedItem.Value);
SearchDirectory();
}
I can never get the first item to trigger the selected index change event - as the SearchDirectory() function is not called. I can understand that it's possibly the case that when the control loads the first item IS selected so when selecting, the index isn't actually changing.
I have tried setting the selected item index to -1, and ClearSelection() on page load, but no luck.
Any ideas? Thanks
You are always resetting the SelectedIndex to -1 on every postback:
this.ddl_SortBy.SelectedIndex = -1;
So put that also in the postback-check:
if (!IsPostBack)
{
this.ddl_SortBy.SelectedIndex = -1;
SearchDirectory();
}
I find myself in the same need to execute a change event on Page_Load like you're expecting.. the thing is that I perceived that in ASP.NET before to put some ListItems it set .SelectecIndex to 0.
So if I put some thing like this.ddl_SortBy.SelectedIndex = -1, after that the debugger still shows 0... so it never turn on -1 and never executes the change event. It's like if ASP.NET always considers the first ListItem as the selected one when nothing (-1) is selected, so force it do -1 or 0 never calls change event at the first.
Searching a bit more: "The default value is 0, which selects the first item in the list."
From http://msdn.microsoft.com/en-us/library/vstudio/system.web.ui.webcontrols.dropdownlist.selectedindex(v=vs.100).aspx so I think we must force the call to event like:
ddl_SortBy_SelectedIndexChanged(null, null);
Move the event handler assignment to OnInit from OnLoad and delete the SelectedIndex line.
protected void Page_Init(object sender, EventArgs e)
{
this.ddl_SortBy.SelectedIndexChanged += new EventHandler(ddl_SortBy_SelectedIndexChanged);
}
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
SearchDirectory();
}
My master page view state was switched off which is why it wasn't working. Though that is not what I want to allow.
My solution was to revert to real form submission data retrieval using Request.Form.
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
SortBy = Convert.ToInt16(Request.Form[this.ddl_SortBy.UniqueID]);
// search directory
SearchDirectory();
}
Works absolutely fine now :)
Thanks everyone.
How about this simple workaround. Set the first item in the drop down to be:
<asp:ListItem Value="-1">(choose how to sort)</asp:ListItem>
That way, the selected index will change and the event will fire when the user selects the desired sort order.
Remove extra fiddling with the drop down from the code behind first.

Enable/Disable the Save button correctly

Let's say we have a Win32 form with a Save toolbar button and some sontrols like a CheckBox are on the form, now we write a one line code for onchange event of checkbox to enable/disable the Save button. Let's say checkbox is selected at first, Save button disabled, now de-select the checkbox, Save button becomes enabled...now select the checkbox again Save button is still enabled...Same for a TextBox for example. Let's say its text is "Hi"...change it to "Hi Bye" , Save is enabled...change it BACK to "Hi" as it was, Save remains enabled...
Is there a model we can use to prevent these wrong enabling/disabling of save button?
You need to write some IF - ELSE code in the CheckedChanged event of the Checkbox. Check what is the current state by inspecting the Checked proeprty of the control (checkbox) ,If yes set the Enabled proeprty of the Button to true, else false.
private void checkBox2_CheckedChanged(object sender, EventArgs e)
{
if (checkBox2.Checked)
button1.Enabled = true;
else
button1.Enabled = false;
}
Assuming checkBox2 is the name of the Checkbox and button1 is the name of the Save button.
You can use the same IF ELSE logic for other controls also. To Set the Value of the Textbox, Use the Text property
TextBox1.Text="I am gonna try something now"l
EDIT : As comecme suggested, If you only want to enable/disable button based on the checbox, It can be done in one line instead of the IF else block like this
button1.Enabled=checkBox2.Checked
You could store the last saved state, and compare the current state to it whenever it changes, to see if they're identical. If so, disable the button.
If these comparisons are expensive, you could make this more efficient, by calculating a hash value over all of the fields that need to be saved, and only doing the proper comparison if the hash of the last saved state matches the hash of the current state.
I prefer to put all my control state checking and setting into a single method:
private void UpdateControls()
{
saveButton.Enabled = checkBox1.Checked;
otherButton.Visible = checkBox2.Checked && textBox.Text.Length > 0;
}
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
UpdateControls();
}
private void checkBox2_CheckedChanged(object sender, EventArgs e)
{
UpdateControls();
}
private void textBox_TextChanged(object sender, EventArgs e)
{
UpdateControls();
}
This means you just have one place in which to check and set the state, and makes it much easier to understand what is going on, especially when you have complex forms. I also prefer boolean expressions rather than if statements when assigning boolean variables, because it caters for both true and false without having to write a separate else statement (which may be forgotten).
I don't get where you're going with your checkbox, but I would use a Boolean variable:
private Boolean _canSave = false;
private Boolean CanSave
{
get { return _canSave; }
set
{
_canSave = value;
MenuSave.Enabled = value;
}
}
public void MenuSave_Click()
{
Save();
}
private void Save()
{
// do your thing
CanSave = false;
}
public void TextBox_TextChanged()
{
CanSave = true;
}
This won't account for disabling the saving menu when you revert the text back to its original. If you want that, you'll have to store the text in the Save() method in a private variable, and compare that to the current text on every TextBox_TextChanged() to determine whether a change compared to the original (i.e. since last save) has occurred.

When you set Checked property in a RadioBox, can you suppress the CheckChanged event?

I'm new to C# and Windows Form but if I have a radiobutton and I call radiobutton1.Checked=true, is there a way for it to not fire the CheckedChange event? I want to distinguish between the user clicking on the radiobutton and me setting the radiobutton programmatically. Is this possible?
Stop trying to defeat the design of the CheckedChanged event. It's specifically supposed to include programmatic changes.
If you want user-triggered changes and not programmatic changes, use the Click event instead. (You may be thinking that you don't want to restrict yourself to mouse clicks, don't worry, there's a MouseClick event for that, Click includes keyboard changes as well.)
Here's a straightforward method of using the event when you feel like it.
private bool SuppressRadioButton1Event { get; set; }
private void radioButton1_CheckedChanged(object sender, EventArgs e)
{
if (!this.SuppressRadioButton1Event)
{
MessageBox.Show("Not suppressed!");
}
}
private void button1_Click(object sender, EventArgs e)
{
this.SetRadioButton1(false);
}
private void SetRadioButton1(bool checkedOn)
{
this.SuppressRadioButton1Event = true;
radioButton1.Checked = checkedOn;
this.SuppressRadioButton1Event = false;
}
A very easy way:
public void radio_OnCheckChanged(object sender, EventArgs e)
{
RadioButton r = sender as RadioButton;
bool isUserChange = r.Tag.Equals(1);
if (isUserChange) blabla
else blabla
r.Tag = null;
}
public void MyMethod()
{
radio1.Tag = 1;
radio.Checked = true;
}
You can use any kind of flag which users can't do by their clicking.But you can do via your code.
Why should your code care who checked the radiobutton?
EDIT: There are ways around this (subclass, flag), but don't. The only "legit" reason I can think of for wanting this is to prevent some side-effect from happening when the value is initially (programatically) displayed, and even that is suspect. Rethink the side-effect, does it really belong on the change-event, or the commit?
More info one why/what would help. On the surface, this looks like a design error.
One (hackish) way to do it would be to subclass RadioButton and override the OnCheckChanged virtual method, suppressing the event if the Checked property has been set programmatically.
However, since radio-buttons belong to a group, the event always fires in pairs (oen for the uncheck, one for the check). You will therefore want to suppress the event for the entire group when you choose the selected button programmatically. Here's an example implementation:
public class CustomRadioButton : RadioButton
{
private bool _suppressCheckedEvent;
public void SetChecked(bool value, bool suppressCheckedEvent)
{
if (!suppressCheckedEvent)
Checked = value;
else
{
SetSupressModeForGroup(true);
Checked = value;
SetSupressModeForGroup(false);
}
}
private void SetSupressModeForGroup(bool suppressCheckedEvent)
{
foreach (var crb in Parent.Controls.OfType<CustomRadioButton>())
crb._suppressCheckedEvent = suppressCheckedEvent;
}
protected override void OnCheckedChanged(EventArgs e)
{
if (!_suppressCheckedEvent)
base.OnCheckedChanged(e);
}
}
In this implementation, changing the checked-state through the Checked property will always fire the event. When you call the SetChecked method, you have the choice to suppress the event.
You could try to attach the event programmatically. Based on my application configuration I check several radio buttons but I don't want to fire events.
To attach an event programmatically:
chbOptionX.CheckedChanged += new System.EventHandler(this.chbShowStockBySizeAndColor_CheckedChanged);

Categories

Resources