ViewState and TextBox behavior

D

Dwight Johnson

I have read countless posts about how people are expecting a textbox
to clear after postbacks, and they do not, and the developer is
confused. And the responses always say "well, this is the way it was
designed to work", and leave it at that. What I NEVER see is how to
get a page to do what all these people clearly WANT it to do.

Example: I have a page that creates a dropdownlist during the
InitializeComponent method, then checks the value of that dropdownlist
and proceeds to fill a textbox with data based on the value of that
dropdown in the Page_Load method. If you step thru the whole process,
the textbox Text property gets the appropriate value.

Now, the dropdownlist has AutoPostBack = true, so, when it changes,
the page is posted back, there is a new value in the dropdownlist, and
the appropriate matching text is assigned to the textbox. But when the
page appears, the textbox contains the original value, not the new
value just put there by the codebehind. Clearly not acting as one
would expect.

I understand why this happens, having read all the helpfully linked
articles about viewstate, etc, that were placed in previous similar
posts.

What I want to know is how to get it to behave the way I EXPECT it to
work. Has anyone figured that out?
 
A

Alvin Bruney [ASP.NET MVP]

From the server, push the value to the page or a hidden field in the page.
After the page loads, use javascript to repopulate the text box. Then
document your fix so that other developers aren't confused.

--
--
Regards,
Alvin Bruney [MVP ASP.NET]

[Shameless Author plug]
The O.W.C. Black Book, 2nd Edition
Exclusively on www.lulu.com/owc $19.99
 
D

Dwight Johnson

Alvin,

Thanks for your reply. Hidden fields and javascript -- how VS6! I
guess I'm going to have to use a separate page to enable this change.
Something is clearly wrong with the way this works, to be so contrary
to expectations.

Dwight
 
P

Patrice

AFAIK you can clear/change values with server side code without any problem.
IMHO the problem is just that this is done to early (before the textbox
values are restored from posted values).

Posting the minimal amount of code that shows the problem should helps to
play with this and solve the problem. If not solved, you could even post
this code so that others can have a crystal claear understanding of what you
are doing...
 
D

Dwight Johnson

Patrice,

Here is a trimmed-down version of my page. I use a class called
CertificateHolderType to fill the dropdownlist. What I want to see is
the new value for commGLLimit for each different holderTypeCode
selected from the dropdown.

using System;

public class CertificateHolderType {

private string certificateHolderTypeCode;
private string certificateHolderTypeDesc;

// constructor
public CertificateHolderType() {
}

public string CertificateHolderTypeCode { get { return
certificateHolderTypeCode; } set { certificateHolderTypeCode =
value; } }
public string CertificateHolderTypeDesc { get { return
certificateHolderTypeDesc; } set { certificateHolderTypeDesc =
value; } }

}

using System;
using System.Collections.Generic;
using System.Web.UI.WebControls;

public partial class TextboxDemoPage : System.Web.UI.Page {

private string errorMsg = string.Empty;
protected ContentPlaceHolder cphZoneMiddleLeft;
string holderTypeCode = "T";
protected DropDownList ddlHolderType = new DropDownList();

// constructor
public TextboxDemoPage() {
Page.Init += new System.EventHandler(Page_Init);
}

private void Page_Init(object sender, EventArgs e) {
InitializeComponent();
}

private void InitializeComponent() {
cphZoneMiddleLeft =
(ContentPlaceHolder)Master.FindControl("cphZoneMiddleLeft");
cphZoneMiddleLeft.Controls.Add(BuildPage_Upper());
}

protected void Page_Load(object sender, EventArgs e) {
try {
ddlHolderType =
(DropDownList)Master.FindControl("cphZoneMiddleLeft").FindControl("ddlHolderType");
if (ddlHolderType != null) {
holderTypeCode = ddlHolderType.SelectedValue;
}
cphZoneMiddleLeft.Controls.Add(BuildPage_Lower());
}
catch (Exception ex) {
errorMsg = ex.ToString();
}
}

private Table BuildPage_Upper() {
Table tbl = new Table();
try {
tbl = BuildPage_Upper_A();
}
catch (Exception ex) {
errorMsg = ex.ToString();
}
return tbl;
}

private Table BuildPage_Upper_A() {
Table tbl = new Table();
TableRow row = new TableRow();
TableCell cell = new TableCell();
Label lbl = new Label();
TextBox txt = new TextBox();
DropDownList ddl = new DropDownList();
try {
// holder type
lbl = new Label();
lbl.Text = "Holder Type";
cell = new TableCell();
cell.Controls.Add(lbl);
row.Controls.Add(cell);
List<CertificateHolderType> lcht = new
List<CertificateHolderType>();
CertificateHolderType lch = new CertificateHolderType();
lch.CertificateHolderTypeCode = "T";
lch.CertificateHolderTypeDesc = "Tenant";
lcht.Add(lch);
lch = new CertificateHolderType();
lch.CertificateHolderTypeCode = "V";
lch.CertificateHolderTypeDesc = "Vendor";
lcht.Add(lch);
lch = new CertificateHolderType();
lch.CertificateHolderTypeCode = "C";
lch.CertificateHolderTypeDesc = "Contractor";
lcht.Add(lch);
ddl.ID = "ddlHolderType";
ddl.DataSource = lcht;
ddl.DataValueField = "CertificateHolderTypeCode";
ddl.DataTextField = "CertificateHolderTypeDesc";
ddl.SelectedValue = holderTypeCode;
ddl.DataBind();
ddl.AutoPostBack = true;
cell = new TableCell();
cell.Controls.Add(ddl);
row.Controls.Add(cell);
tbl.Controls.Add(row);
}
catch (Exception ex) {
errorMsg = ex.ToString();
}
return tbl;
}

private Table BuildPage_Lower() {
Table tbl = new Table();
try {
tbl = BuildPage_Lower_A();
}
catch (Exception ex) {
errorMsg = ex.ToString();
}
return tbl;
}

private Table BuildPage_Lower_A() {
Table tbl = new Table();
TableRow row = new TableRow();
TableCell cell = new TableCell();
Label lbl = new Label();
TextBox txt = new TextBox();
DropDownList ddl = new DropDownList();
try {
int commGLLimit = 0;
switch (holderTypeCode) {
case "T":
commGLLimit = 1000000;
break;
case "V":
commGLLimit = 2000000;
break;
case "C":
commGLLimit = 3000000;
break;
}
// commGLLimit
row = new TableRow();
lbl = new Label();
lbl.Text = "Commercial&nbsp;GL&nbsp;Limit";
cell = new TableCell();
cell.Controls.Add(lbl);
row.Controls.Add(cell);
txt = new TextBox();
txt.Width = Unit.Pixel(100);
txt.MaxLength = 50;
txt.ID = "txtCommGLLimit";
txt.Text = commGLLimit.ToString("N0");
cell = new TableCell();
cell.Controls.Add(txt);
row.Controls.Add(cell);
tbl.Controls.Add(row);
}
catch (Exception ex) {
errorMsg = ex.ToString();
}
return tbl;
}

}
 
P

Patrice

I would trim this even further. I would suggest starting from something such
as :

public partial class _Default : System.Web.UI.Page
{
TextBox t;
DropDownList ddl;

protected void Page_Init(object sender, EventArgs e)
{
// Create controls (ASPX markup could be clearer ?)
t = new TextBox();
ddl = new DropDownList();
ddl.Items.Add(new ListItem("A", "A"));
ddl.Items.Add(new ListItem("B", "B"));
ddl.Items.Add(new ListItem("C", "C"));
ddl.AutoPostBack = true;
form1.Controls.Add(t);
form1.Controls.Add(ddl);
}
protected void Page_Load(object sender, EventArgs e)
{
t.Text = ddl.SelectedValue;
}
}

which is basically what I understand you would want (my understanding is
that you want to populate a textbox control based on the value selected in a
dropdownlist). The LoadComplete event could be even better as it happens
after both ProcessPostBack data phases...

I would start to simplify your code by getting read of exception handling
(IMO it should be processed by a global handler and during the dev phase you
could just use the default error page to make sure you don't miss an error).
Also you have a try block without catch clause that could hide a possible
error + sometimes you seem to check for something that should always exists
(? possibly hiding also errors).
 
D

Dwight Johnson

Patrice,

First of all, thank you! I was able to get my page to work using your
example. Here is what I did:

I built the entire page within the InitializeComponent, itself within
the Page_Init. In the Page_Load I get both controls from the
ContentPlaceHolder, then set the textbox from the value in the
dropdownlist. Excellent. Thank you again!

private void Page_Init(object sender, EventArgs e) {
InitializeComponent();
}

private void InitializeComponent() {
cphZoneMiddleLeft =
(ContentPlaceHolder)Master.FindControl("cphZoneMiddleLeft");
cphZoneMiddleLeft.Controls.Add(BuildPage_Upper());
cphZoneMiddleLeft.Controls.Add(BuildPage_Lower());
}

protected void Page_Load(object sender, EventArgs e) {
try {
ddlHolderType =
(DropDownList)Master.FindControl("cphZoneMiddleLeft").FindControl("ddlHolderType");
txtCommGLLimit =
(TextBox)Master.FindControl("cphZoneMiddleLeft").FindControl("txtCommGLLimit");
if (ddlHolderType != null) {
holderTypeCode = ddlHolderType.SelectedValue;
int commGLLimit = 0;
switch (holderTypeCode) {
case "T":
commGLLimit = 1000000;
break;
case "V":
commGLLimit = 2000000;
break;
case "C":
commGLLimit = 3000000;
break;
}
txtCommGLLimit.Text = commGLLimit.ToString("N0");
}
}
catch (Exception ex) {
errorMsg = ex.ToString();
}
}
 
P

Patrice

Happy it helped. I believe I understood the problem :
- Init : you create some controls
- ASP.NET handles postback data
- You create other controls in the Load event
- but at this step ASP.NET have a "process postback data second try" phase
making newly created control to get ther values from posted form fields
overriding the value you previously defined

By moving all control creation to the Init phase, you do whatever you want
in the load phase and ASP.NET find that all controls are already processed
in the "second try" phase....
 
A

Alvin Bruney [ASP.NET MVP]

I think it is part of the .net framework sdk tools, a separate download.

--
--
Regards,
Alvin Bruney [MVP ASP.NET]

[Shameless Author plug]
The O.W.C. Black Book, 2nd Edition
Exclusively on www.lulu.com/owc $19.99
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,816
Latest member
SapanaCarpetStudio

Latest Threads

Top