The global variable doesn't keep its value - asp.net

The problem is , every time i do a postback my variable "value" doesn't keep it's previous value, and always the dictionary is empty. It doesn't have any previous saved data. How can i make it to save data ?
this is the code :
public partial class MyCart : System.Web.UI.Page
{
public Dictionary<string, string> value = new Dictionary<string, string>();
protected void Page_Load(object sender, EventArgs e)
{
TextBox textbox = new TextBox();
textbox.TextChanged += textbox_TextChanged;
textbox.ID = "textbox" + p.IDProduct.ToString();
Button button = new Button();
}
void textbox_TextChanged(object sender, EventArgs e)
{
value.Add(((TextBox)sender).ID, ((TextBox)sender).Text);
}
}

The global variable are recreated on Postback you probably need to put the variable in ViewState for keep its data between postbacks.
If data is small the its fine with ViewState but if data is large then your might need to think an alternative medium of storage could be database.
To do it with ViewState you would need something like.
public Dictionary<string, string> value = new Dictionary<string, string>();
protected void Page_Load(object sender, EventArgs e)
{
if(ViewState["valDic"] != null)
value = (Dictionary<string, string>)ViewState["valDic"];
TextBox textbox = new TextBox();
textbox.TextChanged += textbox_TextChanged;
textbox.ID = "textbox" + p.IDProduct.ToString();
Button button = new Button();
}
void textbox_TextChanged(object sender, EventArgs e)
{
value.Add(((TextBox)sender).ID, ((TextBox)sender).Text);
ViewState["valDic"] = value;
}
View state is the method that the ASP.NET page framework uses to
preserve page and control values between round trips. When the HTML
markup for the page is rendered, the current state of the page and
values that must be retained during postback are serialized into
base64-encoded strings. This information is then put into the view
state hidden field or fields, MSDN.

After postbacks the variables lose the value as they are recreated..You can depend HTML hidden inputs..
Markup:
<input id="Hidden1" type="hidden" runat="server" value=""/>
Code behind:
Hidden1.value="something";

Related

unable to persist data on postback in dotnetnuke7

I have my website running on dotnetnuke 7.4, i have a checklistbox which i bind on the page load, and after selecting items from it, user clicks on the submit button, the selected items should save in database, however when i click on the submit button, checklistbox gets blank, i tried to enable ViewState at :
Web.config level
Page Level
Control Level
But all in vain, it still unbinds checklistbox because of which everything disappears, i tried the same in plain .net and it works like a charm.
Is there any specific settings in dotnetnuke to support viewstate, or is there any other better option to achieve this.
Here's my code:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
Entities objEntities = new Entities();
List<Entities> obj = objEntities.GetList(2);
chkBox.DataSource = obj;
chkBox.DataTextField = "Name";
chkBox.DataValueField = "ID";
chkBox.DataBind();
}
}
protected void btnSubmit_Click(object sender, EventArgs e)
{
foreach (ListItem item in chkBox.Items)
Response.Write(item.Text + "<br />");
}
There's the issue. Remove that (!IsPostBack) check in your page_load event. Have your code to be like below. Else, only at first page load you are binding the datasource to control which gets lost in postback.
protected void Page_Load(object sender, EventArgs e)
{
Entities objEntities = new Entities();
List<Entities> obj = objEntities.GetList(2);
chkBox.DataSource = obj;
chkBox.DataTextField = "Name";
chkBox.DataValueField = "ID";
chkBox.DataBind();
}
OR, to be more efficient; refactor your code to a method like below and store the data object in Session variable like
private void GetDataSource()
{
List<Entities> obj = null;
if(Session["data"] != null)
{
obj = Session["data"] as List<Entities>;
}
else
{
Entities objEntities = new Entities();
obj = objEntities.GetList(2);
}
chkBox.DataSource = obj;
chkBox.DataTextField = "Name";
chkBox.DataValueField = "ID";
chkBox.DataBind();
Session["data"] = obj;
}
Call the method in your Page_Load event like
protected void Page_Load(object sender, EventArgs e)
{
GetDataSource();
}

Creating dynamic controls in Page_PreRender based on viewstate causes button OnClick event to not work

I realize that dynamic controls should be created within Page_Load and Page_Init in order for them to be registered in the control tree.
I have created a custom control that requires the use of ViewState in a button OnClick event. This ViewState is then used to dynamically create controls.
Since the life-cycle will go: Page Load -> Button Click -> Page PreRender. The view-state will not be updated until "Button Click", thus I am creating my dynamic controls in Page PreRender. However, creating a button and programatically assigning the OnClick EventHandler in Page_PreRender does not work.
Does anyone know how I can get this to work?
btn_DeleteTableRow_Click will not fire. This is setup in CreatePartRows()
Here is my example:
<asp:UpdatePanel ID="up_RMAPart" runat="server" UpdateMode="Conditional" EnableViewState="true" ChildrenAsTriggers="true">
<ContentTemplate>
<div class="button" style="width: 54px; margin: 0px; float: right;">
<asp:Button ID="btn_AddPart" runat="server" Text="Add" OnClick="btn_AddPart_Click" />
</div>
<asp:Table ID="Table_Parts" runat="server" CssClass="hor-zebra">
</asp:Table>
<div class="clear"></div>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="btn_AddPart" EventName="Click" />
</Triggers>
Code Behind:
[Serializable]
public struct Part
{
public string PartName;
public int Quantity;
public int PartID;
public Part(string sPartName, int iQuantity, int iPartID)
{
PartName = sPartName;
Quantity = iQuantity;
PartID = iPartID;
}
}
public partial class RMAPart : System.Web.UI.UserControl
{
private Dictionary<string,Part> m_RMAParts;
private int m_RowNumber = 0;
public Dictionary<string, Part> RMAParts
{
get
{
if (ViewState["m_RMAParts"] != null)
return (Dictionary<string, Part>)ViewState["m_RMAParts"];
else
return null;
}
set
{
ViewState["m_RMAParts"] = value;
}
}
public int RowNumber
{
get
{
if (ViewState["m_RowNumber"] != null)
return Convert.ToInt32(ViewState["m_RowNumber"]);
else
return 0;
}
set
{
ViewState["m_RowNumber"] = value;
}
}
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
RMAParts = new Dictionary<string, Part>();
RowNumber = 0;
RMAParts.Add("PartRow_" + RowNumber.ToString(), new Part());
RowNumber = 1;
CreatePartRows();
}
}
protected void Page_PreRender(object sender, EventArgs e)
{
CreatePartRows();
}
private void CreatePartRows()
{
Table_Parts.Controls.Clear();
TableHeaderRow thr = new TableHeaderRow();
TableHeaderCell thc1 = new TableHeaderCell();
thc1.Controls.Add(new LiteralControl("Part"));
thr.Cells.Add(thc1);
TableHeaderCell thc2 = new TableHeaderCell();
thc2.Controls.Add(new LiteralControl("Quantity"));
thr.Cells.Add(thc2);
TableHeaderCell thc3 = new TableHeaderCell();
thc3.Controls.Add(new LiteralControl(""));
thr.Cells.Add(thc3);
Table_Parts.Rows.Add(thr);
foreach (KeyValuePair<string, Part> kvp in RMAParts)
{
string[] sKey = kvp.Key.Split('_');
TableRow tr = new TableRow();
tr.ID = kvp.Key;
TableCell tc1 = new TableCell();
TextBox tb_Part = new TextBox();
tb_Part.ID = "tb_Part_" + sKey[1];
tb_Part.CssClass = "textbox1";
tc1.Controls.Add(tb_Part);
tr.Cells.Add(tc1);
TableCell tc2 = new TableCell();
TextBox tb_Quantity = new TextBox();
tb_Quantity.ID = "tb_Quanitty_" + sKey[1];
tb_Quantity.CssClass = "textbox1";
tc2.Controls.Add(tb_Quantity);
tr.Cells.Add(tc2);
TableCell tc3 = new TableCell();
Button btn_Delete = new Button();
btn_Delete.ID = "btn_Delete_" + sKey[1];
btn_Delete.CommandArgument = tr.ID;
btn_Delete.Click += new EventHandler(btn_DeleteTableRow_Click);
btn_Delete.Text = "Remove";
tc3.Controls.Add(btn_Delete);
tr.Cells.Add(tc3);
Table_Parts.Rows.Add(tr);
}
}
public void Reset()
{
Table_Parts.Controls.Clear();
RMAParts.Clear();
RowNumber = 0;
RMAParts.Add("PartRow_" + RowNumber.ToString(), new Part());
RowNumber = 1;
CreatePartRows();
}
protected void btn_AddPart_Click(object sender, EventArgs e)
{
RMAParts.Add("PartRow_" + RowNumber.ToString(), new Part());
RowNumber++;
}
protected void btn_DeleteTableRow_Click(object sender, EventArgs e)
{
Button btn = (Button)sender;
TableRow tr = (TableRow)Table_Parts.FindControl(btn.CommandArgument);
Table_Parts.Rows.Remove(tr);
RMAParts.Remove(btn.CommandArgument);
}
}
To ensure that the values of input fields persist across postbacks and that server events are raised:
Use view state to keep track of dynamically created controls.
Re-create the controls with the same IDs in LoadViewState (not Load or PreRender, because then the values of input fields will be lost).
The rest of this answer details how I modified your code to get it to work.
RMAPart.ascx
Just for convenience, you can declare the header row in the .ascx:
<asp:Table ID="Table_Parts" runat="server" CssClass="hor-zebra">
<asp:TableRow>
<asp:TableHeaderCell Text="Part" />
<asp:TableHeaderCell Text="Quantity" />
<asp:TableHeaderCell />
</asp:TableRow>
</asp:Table>
RMAPart.ascx.cs
To keep track of dynamically created rows, maintain a list of row IDs in view state:
public partial class RMAPart : System.Web.UI.UserControl
{
private List<string> RowIDs
{
get { return (List<string>)ViewState["m_RowIDs"]; }
set { ViewState["m_RowIDs"] = value; }
}
In the btn_AddPart_Click handler, generate a new row ID and create the controls for the new row:
protected void btn_AddPart_Click(object sender, EventArgs e)
{
string id = GenerateRowID();
RowIDs.Add(id);
CreatePartRow(id);
}
private string GenerateRowID()
{
int id = (int)ViewState["m_NextRowID"];
ViewState["m_NextRowID"] = id + 1;
return id.ToString();
}
private void CreatePartRow(string id)
{
TableRow tr = new TableRow();
tr.ID = id;
TableCell tc1 = new TableCell();
TextBox tb_Part = new TextBox();
tb_Part.ID = "tb_Part_" + id;
tb_Part.CssClass = "textbox1";
tc1.Controls.Add(tb_Part);
tr.Cells.Add(tc1);
TableCell tc2 = new TableCell();
TextBox tb_Quantity = new TextBox();
tb_Quantity.ID = "tb_Quantity_" + id;
tb_Quantity.CssClass = "textbox1";
tc2.Controls.Add(tb_Quantity);
tr.Cells.Add(tc2);
TableCell tc3 = new TableCell();
Button btn_Delete = new Button();
btn_Delete.ID = "btn_Delete_" + id;
btn_Delete.CommandArgument = id;
btn_Delete.Click += btn_DeleteTableRow_Click;
btn_Delete.Text = "Remove";
tc3.Controls.Add(btn_Delete);
tr.Cells.Add(tc3);
Table_Parts.Rows.Add(tr);
}
In the btn_DeleteTableRow_Click handler, delete the clicked row and update view state:
protected void btn_DeleteTableRow_Click(object sender, EventArgs e)
{
Button btn = (Button)sender;
TableRow tr = (TableRow)Table_Parts.FindControl(btn.CommandArgument);
Table_Parts.Rows.Remove(tr);
RowIDs.Remove(btn.CommandArgument);
}
Hook Page_Load and start things off by creating the first row:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
Reset();
}
}
public void Reset()
{
while (Table_Parts.Rows.Count > 1)
Table_Parts.Rows.RemoveAt(Table_Parts.Rows.Count - 1);
ViewState["m_NextRowID"] = 0;
string id = GenerateRowID();
RowIDs = new List<string> { id };
CreatePartRow(id);
}
Override LoadViewState and re-create the rows using the IDs stored in view state:
protected override void LoadViewState(object savedState)
{
base.LoadViewState(savedState);
foreach (string id in RowIDs)
{
CreatePartRow(id);
}
}
}
Dealing with Parts
The code above doesn't use your Part structure at all. To actually move data between your business objects and the user control, you can add a public method that takes a Part collection and uses it to create rows and populate text boxes, and then add another public method that reads out the values of the text boxes into a Part collection.
The button click isn't being fired because control events are called right after the Load event. Your button isn't in the control hierarchy at the time that the asp.net lifecycle is trying to call your event, so it's being dropped. Remember, it's a round-trip and the control has to exist on postback before the LoadComplete event fires for its event handlers to get called.
Create your dynamic controls in the PreLoad or Load event and you should be OK (you will have access to the full viewstate at that time to make any decisions regarding whether or not you need to dynamically create your delete button for that row).
ASP.net Page Lifecycle Docs: http://msdn.microsoft.com/en-us/library/ms178472(v=vs.100).aspx
I think that Robert has the right answer, but needs to be more clear about WHICH Page.Load he is talking about. There are three page requests here.
Initial Page request, no initial button click yet.
Postback on button click. No processing in Page Load. PreRender call creates the new table rows and the new button and links up the button click event to the new button.
Postback after the client clicks on the new button. You need to re-create the dynamic button in Page Load so that the Click event of the dynamic button doesn't get dropped.
Agree with Robert and Bill.
But to add here, in my opinion only way that you would achieve this is by creating a custom control/web server control (inheriting WebControl class), where you override the CreateChildControls method and RenderContents methods. I think this is what you mean when you said, in one of your comments, you are going to code out a grid-view version.

reatining selection of drodown list which is inside a user control

I have seen two few other posts related to this but I have doubts related to my code. So kindly bear with me.
I have user control which has a text boa and a drop down list and few custom validators.
The user control is added dynamically through a code.
I am using follwoing code to load the dropdownlist inside user control itself
protected void Page_Load(object sender, EventArgs e)
{
ddl_RRC.DataSource = dicRC_Desc;
ddl_RRC.DataTextField = "value";
ddl_RRC.DataValueField = "key";
ddl_RRC.DataBind();
txtRC.Text = Request.Form[txtRC.UniqueID]; //To retain the value of text box
}
I am adding the user control dynamically on Page_Init
protected void Page_Init(object sender, EventArgs e)
{
if (GetPostBackControl(this) == "btnNewRow")
{
custControlCountID++;
}
for (int i = 0; i < custControlCountID; i++)
{
RejRow customControl = (RejRow)LoadControl("~/RejRow.ascx");
customControl.ID = "rejRow" + i;
divHolder.Controls.Add(customControl);
}
}
Viewstate is enabled for both the text box and drop down list.
As I am using the same ID while adding the controls in Page_Init, why the controls are not getting the values from viewstate?
I think the only problem is that you have you're databinding the DropDownList on every postback from Page_Load. Just check the IsPostback-property, e.g.:
protected void Page_Load(object sender, EventArgs e)
{
if(!IsPostBack)
{
ddl_RRC.DataSource = dicRC_Desc;
ddl_RRC.DataTextField = "value";
ddl_RRC.DataValueField = "key";
ddl_RRC.DataBind();
}
txtRC.Text = Request.Form[txtRC.UniqueID]; //To retain the value of text box
}
However, i'm not sure why you need to set the TextBox.Text property from the form-fields since it should store it's Text also in ViewState.

asp.net get the text from a dynamically inserted textbox return null all the time

I am writing a web app in asp.net, in one of my aspx pages I have a static table.
To this table I insert a dynamically textbox control from the code behind (from Page_Load, I create this control dynamically because I do not know if I need to create it or not it depend on a user answer), the problem is when i try to get the textbox text after the user click on a button, I tried every thing i know from Request.Form.Get("id of the control") to Page.FindControl("id of the control"), but nothing works I get null all the time, just to be clear the button that activate the function that get the text from the textbox is insert dynamically to.
Both button and textbox are "sitting" in a table and must remain so, I'd appreciate any help
my code is:
aspx page
<asp:Table ID="TabelMessages" runat="server"></asp:Table>
code behind aspx.cs code:
protected void Page_Load(object sender, EventArgs e)
{
TextBox tb = new TextBox();
tb.ID = "textBox";
tb.Text = "hello world";
TableCell tc = new TableCell();
tc.Controls.Add(tb);
TableRow tr = new TableRow();
tr.Cells.Add(tc);
TabelMessages.Rows.Add(tr);
}
public void Button_Click(object o, EventArgs e)
{
string a = Request.Form.Get("textBox");//does not work
Control aa = Page.FindControl("textBox");//does not work
}
in your
public void Button_Click(object o, EventArgs e)
{
//try searching in the TableMessage.Controls()
}
Alternatively, and depending on what you ultimately want to do, and still use Page_Load:
In your Page Class:
protected TextBox _tb; //this is what makes it work...
protected void Page_Load(object sender, EventArgs e)
{
_tb = new TextBox();
_tb.ID = "textBox";
TableCell tc = new TableCell();
tc.Controls.Add(_tb);
TableRow tr = new TableRow();
tr.Cells.Add(tc);
TabelMessages.Rows.Add(tr);
if (!Page.IsPostBack)
{
_tb.Text = "hello world";
}
}
protected void Button1_Click(object sender, EventArgs e)
{
Label1.Text = _tb.Text; //this will display the text in the TextBox
}
You need to run your code inside the Page_PreInit method. This is where you need to add / re-add any dynamically created controls in order for them to function properly.
See more information about these types of issues in the MSDN article on the ASP.NET Page Life Cycle.
Try changing your Page_Load code to the following:
protected override void OnPreInit(EventArgs e)
{
base.OnPreInit(e);
TextBox tb = new TextBox();
tb.ID = "textBox";
tb.Text = "hello world";
TableCell tc = new TableCell();
tc.Controls.Add(tb);
TableRow tr = new TableRow();
tr.Cells.Add(tc);
TabelMessages.Rows.Add(tr);
}

CheckedChanged event for Dynamically generated Checkbox column in DataGrid(Asp.Net)

I have a datagrid (Asp.Net) with dynamically generated checkbox column..I am not able to generate the checkedChanged event for the checkbox..
Here is my code:
public class ItemTemplate : ITemplate
{
//Instantiates the checkbox
void ITemplate.InstantiateIn(Control container)
{
CheckBox box = new CheckBox();
box.CheckedChanged += new EventHandler(this.OnCheckChanged);
box.AutoPostBack = true;
box.EnableViewState = true;
box.Text = text;
box.ID = id;
container.Controls.Add(box);
}
public event EventHandler CheckedChanged;
private void OnCheckChanged(object sender, EventArgs e)
{
if (CheckedChanged != null)
{
CheckedChanged(sender, e);
}
}
}
and Here is the event
private void OnCheckChanged(object sender, EventArgs e)
{
}
Thanks In advance
When do you add your custom column? If it is on load, then it is too late. Load it on init. I.e. following works with your code:
protected void Page_Init(object sender, EventArgs e)
{
ItemTemplate myTemplate = new ItemTemplate();
myTemplate.CheckedChanged += new EventHandler(myTemplate_CheckedChanged);
TemplateField col = new TemplateField();
col.ItemTemplate = myTemplate;
col.ItemStyle.Wrap = false;
grid.Columns.Add(col);
}
If your checkbox ID's are not being set the same way on every postback, then they can never be connected to the event handlers when it comes time to process the events. Where is your field "id" coming from?

Resources