Before anyone answers this, I found the bug in my code, and posted my answer below. I'm leaving this question up (unless someone really cares) as a cautionary tale to always bind your bleeping GridView.
Preface/Background
I'm (ab)using the ASP.NET WebForms controls in an odd way. I know.
I'm working on an application where students are expected to list some school activities they've participated in. Students can add several rows, and -- just for general workflow reasons -- I decided to separate the GridView that displays their "saved" entries from the "details" area where they add/update their activities.
The Edit/Update pieces work beautifully. I can add new items, use baked-in validation that I tied into my classes (which is what all the extra span tags that have class="error" attributes display). I really wanted to make this idiot-proof, so the button they click to add a new activity will also validate and add their information to the GridView (provided the item passes validation), clear the Details controls, and behave as normal.
Problem Description
I started some basic testing on this, and found that if I edit an activity, break one (or more) of the validation rules in that class, and click the "Add New Activity" button, my GridView reverts that row from the EditItemTemplate back to the normal ItemTemplate.
As far as I can tell, my EditIndex never strays from the row I'm still editing. In fact, if I trigger another postback, the GridView shows the correct EditIndex!
I've tried re-setting the EditIndex and switched my e.Cancel = true to a return statement. Nothing's worked. Considering that the EditIndex's value stays constant through multiple postbacks, I have to think there's something weird going on here.
I've posted the markup and C# code below. Both are pretty absurdly long -- I refactor the hell out of my functions -- so I apologize in advance, and thank anyone brave enough (or bored enough) to offer advice.
Also, I can provide screenshots if anyone would rather see this happening instead of (or in addition to) reading through my markup/code.
GridView
<asp:GridView ID="schoolActivities" AutoGenerateColumns="false" runat="server">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:Button ID="edit" CommandName="Edit" runat="server" Text="Edit" />
</ItemTemplate>
<EditItemTemplate></EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<HeaderTemplate></HeaderTemplate>
<ItemTemplate>
<%# DataBinder.GetPropertyValue(Container.DataItem, "Details") %>
</ItemTemplate>
<EditItemTemplate>Editing...</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<HeaderTemplate>
Months per Year
</HeaderTemplate>
<ItemTemplate><%# DataBinder.GetPropertyValue(Container.DataItem, "MonthsPerYear") %></ItemTemplate>
<EditItemTemplate></EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<HeaderTemplate>Date</HeaderTemplate>
<ItemTemplate>
<%# DataBinder.GetPropertyValue(Container.DataItem, "ActivityDate") %>
</ItemTemplate>
<EditItemTemplate></EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<HeaderTemplate>
Total Hours Outside Class Time
</HeaderTemplate>
<ItemTemplate>
<%# DataBinder.GetPropertyValue(Container.DataItem, "TotalHours") %>
</ItemTemplate>
<EditItemTemplate></EditItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
"Details" section
<br />
<button type="button" id="newActivity" runat="server">Add New Activity</button>
<br />
<fieldset id="schoolActivityFields" runat="server" visible="false">
<legend>Activity</legend>
<span>Details:</span>
<span>
<textarea id="schoolActivityDetails" class="schoolActivityDetails" runat="server"></textarea>
<br />
<span id="schoolActivityDetailsError" class="error" runat="server"></span>
</span>
<br />
<span>Months per Year:</span>
<span>
<select id="schoolActivityMonthsPerYear" runat="server">
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option>5</option>
<option>6</option>
<option>7</option>
<option>8</option>
<option>9</option>
<option>10</option>
<option>11</option>
<option>12</option>
</select>
</span>
<span id="schoolActivityMonthsPerYearError" class="error" runat="server"></span>
<br />
<span>Date:</span>
<span>
<select id="schoolActivityDate" runat="server">
<option>2005</option>
<option>2006</option>
<option>2007</option>
<option>2008</option>
<option>2009</option>
<option>2010</option>
<option>2011</option>
<option>2012</option>
</select>
</span>
<span id="schoolActivityDateError" class="error" runat="server"></span>
<br />
<span>Total Hours:</span>
<span>
<input type="text" id="schoolActivityTotalHours" runat="server" />
</span>
<span id="schoolActivityTotalHoursError" class="error" runat="server"></span>
<br />
<button type="button" id="addActivity" runat="server">Add Activity</button>
<button type="button" id="updateActivity" runat="server" visible="false">Update Activity</button>
<button type="button" id="cancelEditActivity" runat="server" visible="false">Cancel Editing Activity</button>
<button type="button" id="deleteActivity" runat="server" visible="false">Delete Activity</button>
</fieldset>
The C# is monstrous in length, but for any brave souls:
void addActivity_ServerClick(object sender, EventArgs e)
{
AddSchoolActivity();
}
private bool AddSchoolActivity()
{
ResetSchoolActivityErrors();
SchoolActivity activityToAdd = GetSchoolActivity();
try
{
SessionApplication.SchoolActivities.Add(activityToAdd);
BindSchoolActivities();
ResetSchoolActivityFields();
HideSchoolActivityFields();
}
catch (BrokenRuleException)
{
MapSchoolActivityErrors(activityToAdd);
return false;
}
return true;
}
void updateActivity_ServerClick(object sender, EventArgs e)
{
UpdateSchoolActivity();
}
private bool UpdateSchoolActivity()
{
ResetSchoolActivityErrors();
SchoolActivity activityToUpdate = GetSchoolActivity();
try
{
SessionApplication.SchoolActivities[schoolActivities.EditIndex] = activityToUpdate;
ResetSchoolActivitiesEditIndex();
BindSchoolActivities();
ResetSchoolActivityFields();
HideSchoolActivityFields();
}
catch (BrokenRuleException)
{
MapSchoolActivityErrors(activityToUpdate);
SetSchoolActivitiesEditIndex(schoolActivities.EditIndex);
return false;
}
return true;
}
private SchoolActivity GetSchoolActivity()
{
SchoolActivity currentActivity = new SchoolActivity();
currentActivity.Details = schoolActivityDetails.Value;
TryGetSchoolActivityMonthsPerYear(currentActivity);
TryGetSchoolActivityDate(currentActivity);
TryGetSchoolActivityTotalHours(currentActivity);
return currentActivity;
}
private void TryGetSchoolActivityMonthsPerYear(SchoolActivity currentActivity)
{
byte monthsPerYear;
if (byte.TryParse(schoolActivityMonthsPerYear.Value, out monthsPerYear))
{
currentActivity.MonthsPerYear = monthsPerYear;
}
}
private void TryGetSchoolActivityDate(SchoolActivity currentActivity)
{
short activityDate = -1;
if (short.TryParse(schoolActivityDate.Value, out activityDate))
{
currentActivity.ActivityDate = activityDate;
}
}
private void TryGetSchoolActivityTotalHours(SchoolActivity currentActivity)
{
short totalHours = -1;
if (schoolActivityTotalHours.Value.IsNullOrWhiteSpace() == false
&& short.TryParse(schoolActivityTotalHours.Value, out totalHours))
{
currentActivity.TotalHours = totalHours;
}
}
private void ResetSchoolActivityFields()
{
schoolActivityDetails.Value = string.Empty;
schoolActivityMonthsPerYear.SelectedIndex = 0;
schoolActivityDate.SelectedIndex = 0;
schoolActivityTotalHours.Value = string.Empty;
}
private void HideSchoolActivityFields()
{
schoolActivityFields.Visible = false;
}
private void MapSchoolActivityErrors(int activityIndex)
{
SchoolActivity updatedActivity = SessionApplication.SchoolActivities[activityIndex];
MapSchoolActivityErrors(updatedActivity);
}
private void MapSchoolActivityErrors(SchoolActivity updatedActivity)
{
foreach (RuleViolation currentViolation in updatedActivity.GetRuleViolations())
{
schoolActivityErrorMapping[currentViolation].InnerText = currentViolation.ErrorMessage;
}
}
private void ResetSchoolActivityErrors()
{
foreach (RuleViolation currentViolation in schoolActivityErrorMapping.Keys)
{
schoolActivityErrorMapping[currentViolation].InnerText = string.Empty;
}
}
void schoolActivities_RowEditing(object sender, GridViewEditEventArgs e)
{
if (schoolActivities.EditIndex != e.NewEditIndex
&& schoolActivities.EditIndex != -1)
{
ResetSchoolActivityErrors();
SchoolActivity activityToUpdate = GetSchoolActivity();
try
{
SessionApplication.SchoolActivities[schoolActivities.EditIndex] = activityToUpdate;
}
catch (BrokenRuleException)
{
MapSchoolActivityErrors(activityToUpdate);
e.Cancel = true;
}
}
if (e.NewEditIndex != -1)
{
SchoolActivity activityToEdit = SessionApplication.SchoolActivities[e.NewEditIndex];
SetSchoolActivityFields(activityToEdit);
ShowSchoolActivityFields();
ShowModifyActivityButtons();
}
SetSchoolActivitiesEditIndex(e.NewEditIndex);
BindSchoolActivities();
}
private void ShowModifyActivityButtons()
{
addActivity.Visible = false;
updateActivity.Visible = true;
cancelEditActivity.Visible = true;
deleteActivity.Visible = true;
}
private void SetSchoolActivityFields(SchoolActivity activityToEdit)
{
schoolActivityDetails.Value = activityToEdit.Details;
schoolActivityMonthsPerYear.Value = activityToEdit.MonthsPerYear.ToString();
schoolActivityDate.Value = activityToEdit.ActivityDate.ToString();
schoolActivityTotalHours.Value = activityToEdit.TotalHours.ToString();
}
private bool ShowSchoolActivityFields()
{
return schoolActivityFields.Visible = true;
}
private void BindSchoolActivities()
{
schoolActivities.DataSource = SessionApplication.SchoolActivities;
schoolActivities.DataBind();
}
void newActivity_ServerClick(object sender, EventArgs e)
{
if (SessionApplication.SchoolActivities.Count < SchoolActivityList.Rules.MaxCount)
{
if (schoolActivities.EditIndex != -1)
{
if (UpdateSchoolActivity() == false)
{
return;
}
}
else if (schoolActivityFields.Visible)
{
if (AddSchoolActivity() == false)
{
return;
}
}
ShowSchoolActivityFields();
ShowAddActivityButtons();
}
}
private void ShowAddActivityButtons()
{
addActivity.Visible = true;
updateActivity.Visible = false;
cancelEditActivity.Visible = false;
deleteActivity.Visible = false;
}
void ResetSchoolActivitiesEditIndex()
{
SetSchoolActivitiesEditIndex(-1);
}
void SetSchoolActivitiesEditIndex(int rowIndex)
{
schoolActivities.EditIndex = rowIndex;
}
Sigh. I missed a call to my binding function.
UpdateSchoolActivity() should look like this:
private bool UpdateSchoolActivity()
{
ResetSchoolActivityErrors();
SchoolActivity activityToUpdate = GetSchoolActivity();
try
{
SessionApplication.SchoolActivities[schoolActivities.EditIndex] = activityToUpdate;
ResetSchoolActivitiesEditIndex();
BindSchoolActivities();
ResetSchoolActivityFields();
HideSchoolActivityFields();
}
catch (BrokenRuleException)
{
MapSchoolActivityErrors(activityToUpdate);
SetSchoolActivitiesEditIndex(schoolActivities.EditIndex);
BindSchoolActivities(); // That little guy? Don't worry about that little guy.
return false;
}
return true;
}
Related
Please consider this scenario:
I have a simple page and I want to log all controls causing postback. I create this simple page. It contains a grid to show some URLs and when user click on an icon a new tab should open:
<form id="form1" runat="server">
<div>
<table style="width: 100%;">
<tr>
<td style="background-color: #b7ffbb; text-align: center;" colspan="2">
<asp:Button ID="Button3" runat="server" Text="Click Me First" Height="55px" OnClick="Button3_Click" />
</td>
</tr>
<tr>
<td style="background-color: #f1d8fe; text-align: center;" colspan="2">
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false" BackColor="White" OnRowCommand="GridView1_RowCommand">
<Columns>
<asp:BoundField DataField="SiteAddress" HeaderText="Address" />
<asp:TemplateField>
<ItemTemplate>
<asp:ImageButton ID="ImageButton1" ImageUrl="~/download.png" runat="server" CommandArgument='<%# Eval("SiteAddress") %>' CommandName="GoTo" Height="32px" Width="32px" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</td>
</tr>
</table>
</div>
</form>
and code behind:
public partial class WebForm2 : Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Button3_Click(object sender, EventArgs e)
{
List<Address> Addresses = new List<Address>()
{
new Address(){ SiteAddress = "https://google.com" },
new Address(){ SiteAddress = "https://yahoo.com" },
new Address(){ SiteAddress = "https://stackoverflow.com" },
new Address(){ SiteAddress = "https://learn.microsoft.com/}" }
};
GridView1.DataSource = Addresses;
GridView1.DataBind();
}
protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)
{
ScriptManager.RegisterStartupScript(this, this.GetType(), "MyScript", "window.open('" + e.CommandArgument.ToString() + "', '_blank')", true);
}
}
class Address
{
public string SiteAddress { get; set; }
}
every thing is fine till here. Now I create a base class for all of my pages and add below codes for finding postback control:
public class MyPageBaseClass : Page
{
protected override void OnInit(EventArgs e)
{
if (!IsPostBack)
{
}
else
{
var ControlId = GetPostBackControlName(); <------
//Log ControlId
}
base.OnInit(e);
}
private string GetPostBackControlName()
{
Control control = null;
string ctrlname = Page.Request.Params["__EVENTTARGET"];
if (ctrlname != null && ctrlname != String.Empty)
{
control = Page.FindControl(ctrlname);
}
else
{
foreach (string ctl in Page.Request.Form)
{
Control c;
if (ctl.EndsWith(".x") || ctl.EndsWith(".y"))
{
string ctrlStr = ctl.Substring(0, ctl.Length - 2);
c = Page.FindControl(ctrlStr);
}
else
{
c = Page.FindControl(ctl);
}
if (c is System.Web.UI.WebControls.Button ||
c is System.Web.UI.WebControls.ImageButton)
{
control = c;
break;
}
}
}
if (control != null)
return control.ID;
else
return string.Empty;
}
}
and change this line:
public partial class WebForm2 : MyPageBaseClass
Now when I click on icons grid view disappears...(STRANGE...) and nothing happened. When I comment specified line then every thing will be fine...(STRANGE...).
In GetPostBackControlName nothings changed to Request but I don't know why this happened. I checked and I see if I haven't RegisterStartupScript in click event every thing is fine. Please help we to solve this problem.
Thanks
when I click on icons grid view disappears...
ASP.Net page class object instances only live long enough to serve one HTTP request, and each HTTP request rebuilds the entire page by default.
Every time you do a postback, you have a new HTTP request and therefore a new page class object instance and a completely new HTML DOM in the browser. Any work you've done for a previous instance of the page class — such as bind a list of addresses to a grid — no longer exists.
You could fix this by also rebuilding your grid code on each postback, but what I'd really do is skip the whole "RegisterStartupScript" mess and instead make the grid links open the window directly, without a postback at all.
The problem is related to OnInit event. I replaced it with OnPreLoad and every things is fine now.
For search engines: OnInit event has conflict with RegisterStartupScript
I have a repeater using for getting an image nad a radio button on the bottom. I want to achieve a combination of this radio button (repeater speaking) with the property of autoexcluyent feature. How can I achieve it?
As far as I got ...
<asp:Repeater runat="server" ID="repeater1">
<ItemTemplate>
<div class="col-xs-12 col-sm-4 col-md-3">
<asp:Image ID="img" runat="server" ImageUrl="<%#GetRutaImagen(Eval("id").ToString())%>" />
<span>
<asp:RadioButton runat="server" ID="rb1" Text='<%#Eval("description").ToString()%>' GroupName="nameGroup"/>
</span>
</div>
</ItemTemplate>
</asp:Repeater>
With this code I am getting a one radio button per each image but no one autoexcuyent even I am using GroupName property
USING NET FRAMEWORK 4.6.2.
I don't know if easy way to manage this situation however you can manage by below code. It will be good to wrap your contents into update panel so you can prevent page refresh on checkbox changed.
Additionally, IsChecked property being used to initialize checked on page load. You can remove if not required.
.ASPX
<asp:Repeater runat="server" ID="repeater1">
<ItemTemplate>
<div class="col-xs-12 col-sm-4 col-md-3">
<span>
<asp:RadioButton runat="server" ID="rb1" Checked='<%# Eval("IsChecked") %>' AutoPostBack="true" OnCheckedChanged="rb1_CheckedChanged" Text='<%#Eval("description").ToString()%>' />
</span>
</div>
</ItemTemplate>
</asp:Repeater>
.CS
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
List<test1> lst = new List<test1>();
lst.Add(new test1() { Id = 1, description = "R1", IsChecked = false });
lst.Add(new test1() { Id = 3, description = "R2", IsChecked = true });
lst.Add(new test1() { Id = 2, description = "R3", IsChecked = false });
lst.Add(new test1() { Id = 4, description = "R4", IsChecked = false });
repeater1.DataSource = lst;
repeater1.DataBind();
}
}
protected void rb1_CheckedChanged(object sender, EventArgs e)
{
foreach (RepeaterItem item in repeater1.Items)
{
(item.FindControl("rb1") as RadioButton).Checked = false;
}
(sender as RadioButton).Checked = true;
}
After researching between SOF and a few forums I implemented a quite right solution using JS. I am handling another problem related with OnCheckedChanged´s event on RadioButton...
But the initial issue is fixed.
Forum Solution
I am posting the solution that works for me, using as base as a help coming from a forum, hoping it helps others as well with this bug.
REPEATER.
<asp:Repeater runat="server" ID="repeater1" OnItemDataBound="repeater1_ItemDataBound">
<ItemTemplate>
<div class="col-xs-12 col-sm-4 col-md-3">
<asp:Image ID="img" runat="server" ImageUrl="<%#GetRutaImagen(Eval("id").ToString())%>" />
<span>
<asp:RadioButton runat="server" ID="rb1" Text='<%#Eval("description").ToString()%>' GroupName="nameGroup" OnCheckedChanged="rb1_CheckedChanged"/>
</span>
</div>
</ItemTemplate>
</asp:Repeater>
JS
<script>
function SetUniqueRadioButton(nameregex, current) {
for (i = 0; i < document.forms[0].elements.length; i++) {
elm = document.forms[0].elements[i]
if (elm.type == 'radio') {
elm.checked = false;
}
}
current.checked = true;
}
</script>
BACKEND
protected void repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
try
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
RadioButton rbLogoSeleccionado = (RadioButton)e.Item.FindControl("rb1");
string script = "SetUniqueRadioButton('repeater1.*nameGroup',this)";
rbLogoSeleccionado.Attributes.Add("onclick", script);
}
}
catch (Exception ex)
{
PIPEvo.Log.Log.RegistrarError(ex);
throw;
}
}
I use a session to save the hashtable. It has different key-value pairs in it and some of the keys refer to 'List' object.
I have different buttons in the repeater control to change the value of the List and then put it back to hashtable. Then use the same session to save that hashtable. But sometimes the change made get lost in the session. Don't know why. I tried on my test server. It can work fine. While on Prod server, I met this problem.
Any suggestions?
<asp:Repeater ID="rptCountry" runat="server" OnItemDataBound="rptCountry_ItemDataBound" OnItemCommand="rptCountry_ItemCommand">
<ItemTemplate>
<asp:Button ID="btnCountry" runat="server" Text='<%#DataBinder.Eval(Container.DataItem, "Country").ToString() %>' CssClass="iButton Disabled" Enabled="false" UseSubmitBehavior="False" CommandName="Select" />
<asp:Label ID="hdnCountryCode" runat="server" Text='<%#DataBinder.Eval(Container.DataItem, "CountryCode")%>' Visible="false" />
</ItemTemplate>
</asp:Repeater>
protected void rptCountry_ItemCommand(object sender, RepeaterCommandEventArgs e)
{
if (e.CommandName.Equals("Select"))
{
Button btnCountry = (Button)e.Item.FindControl("btnCountry");
Label hdnCountryCode = (Label)e.Item.FindControl("hdnCountryCode");
if (Session["SearchFilter"] != null)
{
Hashtable htSearchFilter = (Hashtable)Session["SearchFilter"];
List<string> countries = (List<string>)htSearchFilter["Country"];
if (countries != null && countries.Count > 0)
{
bool countriesExists = false;
foreach (string country in countries)
{
if (country.Equals(hdnCountryCode.Text.Trim()))
{
countriesExists = true;
}
}
if (!countriesExists)
{
countries.Add(hdnCountryCode.Text.Trim());
btnCountry.CssClass = "iButton Active";
}
else
{
countries.Remove(hdnCountryCode.Text.Trim());
btnCountry.CssClass = "iButton";
}
}
else
{
countries.Add(hdnCountryCode.Text.Trim());
btnCountry.CssClass = "iButton Active";
}
htSearchFilter["Country"] = countries;
Session["SearchFilter"] = htSearchFilter;
ProvinceReloadControl(countries);
}
}
InitControl();
}
I am trying to find the formview inside my listview on the page load. However, my result is always null. I called the DataBind method first but still nothing.
Code Behind
protected void Page_Load(object sender, EventArgs e)
{
String list = itemdropdownlist.SelectedValue;
switch (list)
{
case "Section Item":
SectionListView.DataBind();
//SectionListView.Enabled = false;
var temp = (FormView)SectionListView.FindControl("SectionFormView");
temp.Enabled = true;
renderView(SectionListView, "hidden"); // hide listview on page load
break;
}
}
ASP.net code
<InsertItemTemplate>
<tr style="">
<td>
<div style="font-size: .8em;">
<asp:FormView ID="SectionFormView" runat="server" DataKeyNames="SectionItemID" DataSourceID="SectionDataSource">
<ItemTemplate>
<asp:Button ID="InsertButton" runat="server" Text="Insert" OnClick="SectionItemButton_Click" Font-Size="1.2em" />
<asp:Button ID="CancelButton" runat="server" CommandName="Cancel" Text="Clear" Font-Size="1.2em" />
<asp:Label ID="SectionItemLabel" runat="server" Text="SectionItem" Font-Bold="true" Font-Size="1.2em" />
<asp:TextBox ID="SectionItemTextBox" runat="server" />
<asp:Label ID="SectionItemSubLabel" runat="server" Text="SectionItem Label" Font-Bold="true" Font-Size="1.2em" />
<asp:TextBox ID="SectionItemLabelTextBox" runat="server" />
</ItemTemplate>
</asp:FormView>
</div>
</td>
</tr>
</InsertItemTemplate>
<ItemTemplate>
You got that error, because the listview was not binded yet, so i think the best way would be to do all this on the ItemDataBound event. You would find the FormView like:
if (e.Item.ItemType == ListViewItemType.DataItem)
{
FormView SFormView= (FormView)e.Item.FindControl("SectionFormView");
if (SFormView!= null)
{
//code here
}
}
You could use this code to find about anything. I used it before to find Literals that I created in code behind. Use this code to find your FormView
private readonly List<FormView> _foundControls = new List<FormView>();
public IEnumerable<FormView> FoundControls
{
get { return _foundControls; }
}
public void FindChildControlsRecursive(Control control)
{
foreach (Control childControl in control.Controls)
{
if (childControl.GetType() == typeof(FormView))
{
_foundControls.Add((FormView)childControl);
}
else
{
FindChildControlsRecursive(childControl);
}
}
}
FindChildControlsRecursive(<Insert relevent Code Here: Whatever element you want to search inside of like your listView, find that using FindControl>);
FormView[] strControl = new FormView[200];
strControl = FoundControls.ToArray();
foreach (FormView i in strControl)
{
if (i.ID.Equals("< insert controlId of your FormView>"))
{
// do something when you find it
}
}
I'm trying to post data to the same page after postback with the help of ViewState. I fill out the contents of the page and post the form and display the input on the same page but the validator says that the firstname cannot be null while I just filled out the textbox before I submitted the form.
Default.aspx
<asp:Content ContentPlaceHolderID="Main" runat="server" EnableViewState="true">
<form id="form1" runat="server">
<div>
<table>
<tr>
<td>
<asp:Label ID="lbl1" Text="First Name" runat="server" />
</td>
<td>
<asp:TextBox ID="tFirstName" runat="server" />
</td>
<td>
<asp:RequiredFieldValidator ControlToValidate="tFirstName" ErrorMessage="This field cannot be empty."
runat="server" />
</td>
</tr>
<tr>
<td>
<asp:Label ID="lbl2" Text="Last Name" runat="server" />
</td>
<td>
<asp:TextBox ID="tLastName" runat="server" />
</td>
</tr>
</table>
</div>
<asp:Button ID="id" Text="Submit" runat="server" OnClick="Submit" />
<div>
<p>
<asp:Label ID="lTest" runat="server" /></p>
</div>
<asp:Label ID="lSubmit" runat="server" />
</form>
Default.aspx.cs
protected void Page_Load(object sender, EventArgs e)
{
if (Page.IsPostBack)
{
tFirstName.Text = (string)ViewState["tFirstName"];
tLastName.Text = (string)ViewState["tLastName"];
}
else
{
ViewState["tFirstName"] = tFirstName.Text;
ViewState["tLastName"] = tLastName.Text;
}
}
protected void Submit(object sender, System.EventArgs args)
{
try
{
lTest.Text = tFirstName.Text + " " tLastName.Text;
}
catch (Exception ex)
{
throw;
}
}
It seems my logic was wrong. The correct condition should be Page_Load() function:
if (!Page.IsPostBack)
{
tFirstName.Text = (string)ViewState["tFirstName"];
tLastName.Text = (string)ViewState["tLastName"];
}
It should be if (!Page.IsPostBack) instead of if (Page.IsPostBack)
:D
Have fun!
You are getting too confuse on this,
Below is the possible way to solve your issues. Before this, please learn about postback in page load
Seems you are passing the null values to the ViewState,
if (Page.IsPostBack)
{
tFirstName.Text = (string)ViewState["tFirstName"];
tLastName.Text = (string)ViewState["tLastName"];
}
else
{
ViewState["tFirstName"] = tFirstName.Text;
ViewState["tLastName"] = tLastName.Text;
}
Proceed as following
protected void Page_Load(object sender, EventArgs e)
{
if(IsPostback==true)
{
if(ViewState["tFirstName"]!=null && ViewState["tLastName"]!=null)
{
tFirstName.Text = (string)ViewState["tFirstName"];
tLastName.Text = (string)ViewState["tLastName"];
}
}
}
protected void Submit(object sender, System.EventArgs args)
{
try
{
ViewState["tFirstName"] = tFirstName.Text;
ViewState["tLastName"] = tLastName.Text;
lTest.Text = tFirstName.Text + " " tLastName.Text;
}
catch (Exception ex)
{
throw;
}
}
I only want to point out, that you do NOT have to reassign values to the textboxes after a Postback. This is the normal asp.net web control behavior when EnableViewstate is turned on.
Remove your code from Page_Load and you should notice that textboxes remember values after a postback (unless you specifically remove it in behind code like tFirstName.Text = "")