I am quite new to ASP and I have been stuck on an issue for about a week. The issue is probably something to do with the Asp Page Life Cycle but I am unable to find how this can be resolved. The issue is that skipto(..) is never called when I click the LinkButton (that were created on first Page Load), which means the LinkButtons are not rendered.
Sample Code below:
// Code Behind
protected void Page_Load(object sender, EventArgs e)
{
loadData();
if (!Page.IsPostBack)
{
skiptof();
}
}
public void loadData() {
// Loads from database
}
public void skipto(object sender, EventArgs e)
{
LinkButton btn = sender as LinkButton;
if (btn != null)
{
if (btn.CommandArgument != null && btn.CommandArgument != "0")
{
int currPage = 1;
int.TryParse(btn.CommandArgument, out currPage);
skiptof(currPage);
}
}
}
public void skiptof(int currPage = 1)
{
int lastPage = // calculate from LoadData()
string pageDisabled = "";
// pages
HtmlGenericControl ul = new HtmlGenericControl("ul");
while (pageCount <= lastPage)
{
// Disable the current page
pageDisabled = pageCount == currPage ? " class=\"disabled\"" : "";
HtmlGenericControl pagesli = new HtmlGenericControl("li");
if (pageDisabled != "")
{
pagesli.Attributes.Add("class", "disabled");
}
LinkButton pagesPageLink = new LinkButton();
pagesPageLink.Click += new EventHandler(skipto);
pagesPageLink.CommandArgument = pageCount.ToString();
pagesPageLink.Text = pageCount.ToString();
pagesli.Controls.Add(pagesPageLink);
ul.Controls.Add(pagesli);
pageCount += 1;
}
pagination.Controls.Add(ul);
}
// page
<asp:ScriptManager ID="ScriptManager1" runat="server"/>
<asp:UpdatePanel runat="server" id="UpdatePanel" UpdateMode="Conditional">
<ContentTemplate>
<div id="details" runat="server"></div>
<div class="pagination text-center" id="pagination" runat="server"></div>
</ContentTemplate>
</asp:UpdatePanel>
Your problem is:
You didn't bind the data again on postback, I've modified your code a little bit, there are several problems:
in the method skipof:
public void skiptof(int currPage = 1) {
//Clear the controls here then add them again
pagination.Controls.Clear();
int lastPage = // calculate from LoadData()
string pageDisabled = "";
HtmlGenericControl ul = new HtmlGenericControl("ul");
while (pageCount <= lastPage) {
// Disable the current page
pageDisabled = pageCount == currPage ? " class=\"disabled\"" : "";
HtmlGenericControl pagesli = new HtmlGenericControl("li");
if (pageDisabled != "") {
pagesli.Attributes.Add("class", "disabled");
}
LinkButton pagesPageLink = new LinkButton();
// you can directly assign the method to be called here, there is no need to create a new EventHandler
pagesPageLink.Click += PagesPageLink_Click;
pagesPageLink.CommandArgument = pageCount.ToString();
pagesPageLink.Text = pageCount.ToString();
pagesli.Controls.Add(pagesPageLink);
ul.Controls.Add(pagesli);
pageCount += 1;
}
pagination.Controls.Add(ul);
}
You didn't bind the data again in postback, so I modified it:
Page Load:
protected void Page_Load(object sender, EventArgs e) {
//Remove the Page.IsPostBack checking
skiptof();
}
Please take note that the controls you added dynamically will be cleared and you have to add it again on postback to avoid data lost.
Then you'll be able to get the value on PagesPageLink_Click event:
The whole sample is here:
http://pastie.org/10503291
Related
I have a ImageButton which will show Calendar after it is clicked. I want to stop page refresh when the ImageButton is clicked, but I've tried a couple of ways and none of them work. Is it possible to avoid page refresh and just show the calendar after the Image Button is clicked?
Here is my c# code
TableRow first = new TableRow();
TableCell four = new TableCell();
ImageButton btnDateToggle = new ImageButton();
btnDateToggle.ID = $"btnDateToggle_{j}";
btnDateToggle.ImageUrl = "images/icon2.gif";
btnDateToggle.Click += new ImageClickEventHandler(BtnDateToggle_Click);
Calendar dateddl = new Calendar();
dateddl.ID = $"dateddl_{j}"
dateddl.Width = 250;
dateddl.Visible = false;
dateddl.SelectionChanged += new EventHandler(Dateddl_SelectionChanged);
four.Controls.Add(btnDateToggle);
four.Controls.Add(dateddl);
first.Cells.Add(four);
tasksTable.Rows.Add(first);
ChildPane.ContentContainer.Controls.Add(tasksTable);
ChildAccordion.Panes.Add(ChildPane);
ParentPane.ContentContainer.Controls.Add(ChildAccordion);
MasterAccordion.Panes.Add(ParentPane);
MyContent.Controls.Add(MasterAccordion);
ChildPane and ParentPane are AccordionPane Object. ChildAccordion is an Accordion Object
protected void BtnDateToggle_Click(object sender, EventArgs e)
{
string btnDateToggleID = ((Control)sender).ID;
string index = btnDateToggleID.Substring(btnDateToggleID.IndexOf('_') + 1);
Calendar dateddl = (Calendar)FindControlRecursive(Page, $"dateddl_{index}");
dateddl.Visible = !dateddl.Visible;
}
protected void Dateddl_SelectionChanged(object sender, EventArgs e)
{
Calendar dateddl = (Calendar)sender;
string dateddlID = dateddl.ID;
string index = dateddlID.Substring(dateddlID.IndexOf('_') + 1);
TextBox textBox = (TextBox)FindControlRecursive(Page, $"txtDate_{index}");
dateddl.Visible = false;
textBox.Text = dateddl.SelectedDate.ToShortDateString();//.ToString("MM/dd/yyyy");
}
Here is my client side code (.aspx)
<asp:Content ID="Content1" runat="server">
<div>
<asp:Panel ID="MyContent" runat="server">
<ajaxToolkit:Accordion ID="MasterAccordion" runat="server"> </ajaxToolkit:Accordion>
</asp:Panel>
</div>
I've added two text boxes dynamically on the aspx page.
I would like to get values from those two text boxes on the server side after postback (after Btn1 is clicked).
And here is my first problem - controls are not found.
I've tried to find controls with:
Page.FindControl("txt4");
What is wrong with this? Isn't the whole page posted back with all the controls in it?
My other question is - where in the code to get those values? In the Page_load event, before they are re-added? I guess when Btn1_Click event is triggered, those two controls are already re-added, so values from original postback are lost? (Page_load event is triggered before Btn1_Click).
I am really struggling with this.
It is much easier if controls are added through markup - they are directly accesible in code behind by theirs ID. But on the project that I work currently controls are mostly added dynamically, and a lot of them.
Code behind:
public partial class About : Page
{
protected void Page_Load(object sender, EventArgs e)
{
btn1.Click += Btn1_Click;
if(IsPostBack)
{
System.Web.UI.Control txt4_dynamic = Page.FindControl("txt4");
System.Web.UI.Control txt5_dynamic = Page.FindControl("txt5");
if(txt4_dynamic != null)
{
string str1 = ((TextBox)txt4_dynamic).Text;
}
if (txt5_dynamic != null)
{
string str1 = ((TextBox)txt5_dynamic).Text;
}
}
TextBox txt4 = new TextBox();
txt4.ClientIDMode = ClientIDMode.Static;
txt4.ID = "txt4";
TextBox txt5 = new TextBox();
txt5.ClientIDMode = ClientIDMode.Static;
txt5.ID = "txt5";
panel1.Controls.Add(txt4);
panel1.Controls.Add(txt5);
}
private void Btn1_Click(object sender, EventArgs e)
{
System.Web.UI.Control txt4_dynamic = Page.FindControl("txt4");
System.Web.UI.Control txt5_dynamic = Page.FindControl("txt5");
if (txt4_dynamic != null)
{
string str1 = ((TextBox)txt4_dynamic).Text;
}
if (txt5_dynamic != null)
{
string str1 = ((TextBox)txt5_dynamic).Text;
}
}
}
Markup:
<asp:Content ID="BodyContent" ContentPlaceHolderID="MainContent" runat="server">
<asp:Button ID="btn1" runat="server" Text="Button" />
<asp:Panel ID="panel1" runat="server" ClientIDMode="Static">
</asp:Panel>
</asp:Content>
UPDATE:
I've updated my code with:
protected void Page_Init(object sender, EventArgs e)
{
if(IsPostBack)
{
TextBox txt4 = new TextBox();
txt4.ClientIDMode = ClientIDMode.Static;
txt4.ID = "txt4";
TextBox txt5 = new TextBox();
txt5.ClientIDMode = ClientIDMode.Static;
txt5.ID = "txt5";
panel1.Controls.Add(txt4);
panel1.Controls.Add(txt5);
string st1 = txt4.Text;
string st2 = txt5.Text;
System.Web.UI.Control txt4_dynamic = Page.FindControl("txt4");
System.Web.UI.Control txt5_dynamic = Page.FindControl("txt5");
if (txt4_dynamic != null)
{
string str1 = ((TextBox)txt4_dynamic).Text;
}
if (txt5_dynamic != null)
{
string str1 = ((TextBox)txt5_dynamic).Text;
}
}
}
I've checked the code in debugger - controls are added on postback, but values for st1, st2, txt4_dynamic and txt5_dynamic are still empty / null.
UPDATE 2:
There were two problems:
Finding control should be done with:
Page.Controls[0].FindControl("MainContent").FindControl("txt4");
Code above finds controls text only in controls events (and they are triggered after Page_Load).
So: Everything can stay as I originally posted - the only change needed is code for finding control, which must be in click event. If this same code is in Page_Load event, it will not work.
Please change the code to as below (basically move the dynamic control creation/addition to Page_Init):
public partial class About : Page
{
protected void Page_Init(object sender, EventArgs e)
{
TextBox txt4 = new TextBox();
txt4.ClientIDMode = ClientIDMode.Static;
txt4.ID = "txt4";
TextBox txt5 = new TextBox();
txt5.ClientIDMode = ClientIDMode.Static;
txt5.ID = "txt5";
panel1.Controls.Add(txt4);
panel1.Controls.Add(txt5);
}
protected void Page_Load(object sender, EventArgs e)
{
btn1.Click += Btn1_Click;
if (IsPostBack)
{
System.Web.UI.Control txt4_dynamic = Page.Controls[0].FindControl("MainContent").FindControl("txt4");
System.Web.UI.Control txt5_dynamic = Page.Controls[0].FindControl("MainContent").FindControl("txt5");
if (txt4_dynamic != null)
{
string str1 = ((TextBox)txt4_dynamic).Text;
}
if (txt5_dynamic != null)
{
string str1 = ((TextBox)txt5_dynamic).Text;
}
}
}
private void Btn1_Click(object sender, EventArgs e)
{
System.Web.UI.Control txt4_dynamic = Page.Controls[0].FindControl("MainContent").FindControl("txt4");
System.Web.UI.Control txt5_dynamic = Page.Controls[0].FindControl("MainContent").FindControl("txt5");
if (txt4_dynamic != null)
{
string str1 = ((TextBox)txt4_dynamic).Text;
}
if (txt5_dynamic != null)
{
string str1 = ((TextBox)txt5_dynamic).Text;
}
}
}
Control tree is created at server side on each postback. Since controls are added dynamically they need to be added on each postback, which you are already doing.
Reason for moving that code to Page_Init event is that, values posted from clientside are set in LoadPostData event which happens after Page_Init and before Page_Load.
When you have the code in Page_Init, by the time LoadPostData event happens control tree is already created and posted value is correctly set.
When you had the code in Page_Load, LoadPostData event happened even before the control was created and posted value was not set.
First time poster, long time lurker. I am having some trouble with my ASP.NET page, and I hope someone can help me resolve my issue.
Basically, I have a bunch of checkboxes in a gridview, and two buttons: a 'find' button, and a 'save' button. The 'find' can set the value of the checkbox, but if a user unchecks it, I want to capture that change when the user hits 'save'. Currently, it does not work.
Relevant ASPX:
<%# Page Language="C#" AutoEventWireup="true" EnableViewState="true" CodeBehind="FindTransactions.aspx.cs" Inherits="Basic.FindTransactions" MasterPageFile="~/Trans.Master" %>
Relevant Code Behind here:
Page:
public partial class FindTransactions : System.Web.UI.Page
{
GridView _gridview = new GridView() { ID = "_gridView" };
DataTable _datatable = new DataTable();
Int32 _buyerID = new Int32();
protected void Page_Load(object sender, EventArgs e)
{
}
"Find" button:
protected void Find_Click(object sender, EventArgs e)
{
//truncated
_datatable.Rows.Add(
//filled with other data from a custom object.
);
ViewState["_datatable"] = _datatable;
ViewState["_buyerID"] = _buyerID;
BuildGridView((DataTable)ViewState["_datatable"],(Int32)ViewState["buyerID"]);
}
BuildGridView function:
protected void BuildGridView(DataTable d, Int32 b)
{
_gridview.DataKeyNames = new String[] {"Transaction ID"};
_gridview.AutoGenerateColumns = false;
_gridview.RowDataBound += new GridViewRowEventHandler(OnRowDataBound);
for(Int32 i = 0; i < d.Columns.Count; i++)
{
Boundfield boundfield = new BoundField();
boundfield.DataField = d.Columns[i].ColumnName.ToString();
boundfield.HeaderText = d.Columns[i].ColumnName.ToString();
_gridview.Columns.Add(boundfield);
}
_gridview.DataSource = d;
_gridview.DataBind();
//truncated
Panel1.Controls.Add(_gridview);
}
Row Bound Event handler:
protected void OnRowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
String controlID = "checkBox";
CheckBox c = new CheckBox() { ID = controlID};
c.Enabled = true;
Boolean success;
Boolean v;
success = Boolean.TryParse(e.Row.Cells[8].Text, out v);
e.Row.Cells[8].Controls.Add(c);
if (success)
{
c.Checked = v;
if (c.Checked)
{
//Will uncomment once other things work
//e.Row.Visible = false;
}
}
else
{
c.Checked = false;
}
}
}
All of that works. Here is where it starts to break down:
"Save" button:
protected void Save_Click(object sender, EventArgs e)
{
//Both for troubleshooting and both return 0. (Expected for datatable)
Label1.Text = _gridview.Rows.Count.ToString();
Label2.Text = _datatable.Rows.Count.ToString();
/*truncated
*/
if (grid.Rows.Count == 0)
{
BuildGridView((DataTable)ViewState["infoTable"], (Int32)ViewState["guestID"]);
}
foreach (GridViewRow r in grid.Rows)
{
if (r.RowType == DataControlRowType.DataRow)
{
CheckBox cb = (CheckBox)r.FindControl("checkBox");
if (cb != null && cb.Checked)
{
//This never seems to modify the label.
//Will put code to modify database here.
Label2.Text += "Hi " + r.RowIndex.ToString();
}
}
}
}
After I hit the save button, PostBack occurs and GridView is empty (Rows.Count is 0). ViewState appears to be lost before I get a chance to loop through the GridView rows to determine the checkbox values.
At the end of it all, I just want to capture the status of those checkboxes, changed by user interaction or not, by hitting the 'Save' button.
I found some other articles, but a lot of them haven't worked when I tried implementing the various fixes.
This one seems to be the closest that describes my issue, and the code is structured similarly, but I don't quite understand how to implement the fix: GridView doesn't remember state between postbacks
[New simplified code to illustrate problem:]
namespace GridViewIssue
{
public partial class GridViewNoMaster : System.Web.UI.Page
{
GridView _gridView = new GridView() { ID = "_gridView" };
DataTable _dataTable = new DataTable();
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Find_Click(object sender, EventArgs e)
{
BuildDataTable();
List<String> list = new List<String>();
list.Add("1");
list.Add("User");
list.Add("10/12/2014");
foreach (String s in list)
{
_dataTable.Rows.Add(
list[0],
list[1],
list[2]
);
}
BuildGridView();
//Feedback.Text = _gridView.Rows.Count.ToString();
}
protected void Save_Click(object sender, EventArgs e)
{
Feedback.Text = "Save Clicked, PostBack: " + IsPostBack + ", GridView Row Count: " + _gridView.Rows.Count + ", GridView ViewState: " + _gridView.EnableViewState;
foreach (GridViewRow r in _gridView.Rows)
{
if(r.RowType == DataControlRowType.DataRow)
{
Feedback.Text = "In DataRow type" + _gridView.Rows.Count;
}
}
}
protected void BuildDataTable()
{
_dataTable.Columns.Add("Transaction ID", typeof(String));
_dataTable.Columns.Add("Name", typeof(String));
_dataTable.Columns.Add("Date", typeof(String));
}
protected void BuildGridView()
{
for (Int32 i = 0; i < _dataTable.Columns.Count; i++)
{
BoundField b = new BoundField();
b.DataField = _dataTable.Columns[i].ColumnName.ToString();
b.HeaderText = _dataTable.Columns[i].ColumnName.ToString();
_gridView.Columns.Add(b);
}
_gridView.DataKeyNames = new String[] { "Transaction ID" };
_gridView.AutoGenerateColumns = false;
_gridView.DataSource = _dataTable;
_gridView.DataBind();
Panel1.Controls.Add(_gridView);
}
}
}
Here i am updating the gridview value but the value is not updating..TextBox txtID,TextBox txtName,TextBox txtAge retains the older value only and the value is not getting updated..Can anyone tel me like what am i doing wrong here
Here is my code
protected void gvTemp_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
CreateDataSkeletton(Convert.ToInt16(Session["intTabIndex"]));
GridViewRow row = (GridViewRow)gvTemp.Rows[e.RowIndex];
int autoid = Int32.Parse(gvTemp.DataKeys[e.RowIndex].Value.ToString());
int id = Convert.ToInt32(gvTemp.DataKeys[e.RowIndex].Values[0].ToString());
activeTabIndex = Convert.ToInt16(Session["activeTabIndex"]);
TextBox txtID = ((TextBox)gvTemp.Rows[e.RowIndex].FindControl("txtId"));
TextBox txtName = (TextBox)gvTemp.Rows[e.RowIndex].FindControl("txtName");
TextBox txtAge = (TextBox)gvTemp.Rows[e.RowIndex].FindControl("txtAge");
dataSetInSession.Tables["Days" + activeTabIndex.ToString()].Rows[e.RowIndex]["ID"] = txtID.Text;
dataSetInSession.Tables["Days" + activeTabIndex.ToString()].Rows[e.RowIndex]["Name"] = txtName.Text;
dataSetInSession.Tables["Days" + activeTabIndex.ToString()].Rows[e.RowIndex]["Age"] = txtAge.Text;
gvTemp.DataSource = dataSetInSession.Tables["Days" + activeTabIndex.ToString()];
gvTemp.DataBind();
gvTemp.EditIndex = -1;
}
and
private void CreateDataSkeletton(int intTabIndex)
{
dataSetInSession = new DataSet();
Session["intTabIndex"] = intTabIndex;
if (Session["dataSetInSession"] != null)
{
dataSetInSession = (DataSet)Session["dataSetInSession"];
}
if (dataSetInSession.Tables["Days" + intTabIndex].Rows.Count > 0)
{
gvTemp.DataSource = dataSetInSession.Tables["Days" + intTabIndex];
gvTemp.DataBind();
}
else
{
gvTemp.DataSource = dataSetInSession.Tables["Days"];
gvTemp.DataBind();
}
temp.Controls.Add(gvTemp);
}
Any suggestion??
EDIT(1):
protected void Page_Init(object sender, EventArgs e)
{
if (!IsPostBack)
{
AddDataTable();
}
dataSetInSession = new DataSet();
if (Session["dataSetInSession"] != null)
{
dataSetInSession = (DataSet)Session["dataSetInSession"];
}
if (Session["dynamicTabIDs"] != null)
{
//if dynamicTabIDs are in session, recreating the Tabs
//that are associated with the Tab IDs
//and adding them to the TabContainer that will contain
//all of the dynamic tabs.
//retrieving the tab IDs from session:
dynamicTabIDs = (List<string>)Session["dynamicTabIDs"];
if (TabContainerContent.ActiveTabIndex == -1)
{
TabContainerContent.ActiveTabIndex = Convert.ToInt16(Session["intTabIndex"]);
}
CreateDataSkeletton(Convert.ToInt16(Session["intTabIndex"]));
//looping through each TabID in session
//and recreating the TabPanel that is associated with that tabID
foreach (string tabID in dynamicTabIDs)
{
//creating a new TabPanel that is associated with the TabID
AjaxControlToolkit.TabPanel tab = new AjaxControlToolkit.TabPanel();
//TabContainerContent.ActiveTabIndex = tab;
//Setting the ID property of the TabPanel
tab.ID = tabID;
//setting the TabPanel's HeaderText
tab.HeaderText = "Days " + (TabContainerContent.Tabs.Count + 1).ToString();
//creating a Label to add to the TabPanel...at this point you'll have to
//create whatever controls are required for the tab...
Label tabContent = new Label();
//Giving the Label an ID
tabContent.ID = "lbl_tab_" + TabContainerContent.Tabs.Count.ToString();
//Setting the Label's text
tabContent.Text = "Tab " + (TabContainerContent.Tabs.Count + 1).ToString();
//Adding the Label to the TabPanel
tab.Controls.Add(tabContent);
//Adding the TabPanel to the TabContainer that contains the dynamic tabs
TabContainerContent.Tabs.Add(tab);
}
}
else
{ //Creating a new list of dynamicTabIDs because one doesn't exist yet in session.
dynamicTabIDs = new List<string>();
}
}
protected void Page_Load(object sender, EventArgs e)
{
}
Read Page Life Cycle
And you will get, that if you want to bind in code-behind, you should do it in Init Event, other wise there are no events will fire.
It seems to be Page.IsPostback problem.Need to add Page.IsPostback property in your page_load like
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
// Put your code inside that.
}
}
Actually your control is getting new value but when you click for updation then it calls old value from page_load.So try to put Page.IsPostback into your page_load event,Just like i mentioned.
I hope it helps.
I have this code which adds a x number of views to a Multiview control. The Multiview control exist on the page with only one view. on page init I create x number of views with a GridView control added to each of these views when I come to loop through to find which one I want to show the Multiview control says it has only 1 view.
protected void variantRepeat_ItemCommand(object source, RepeaterCommandEventArgs e)
{
if (e.CommandSource.GetType() == typeof(LinkButton))
{
string theID = ((LinkButton)e.CommandSource).CommandArgument.ToString();
ViewCollection views = prodView.Views; //this has only 1 view the one that has been added on the source view of the .aspx page
foreach (View toDisplay in views)
{
if (toDisplay.ID == theID)
prodView.SetActiveView(toDisplay);
}
}
}
The code above loops to find the view and display it. Why do all the views disappear, I've stepped through and at init and after it has finished processing database queries it has x number of views > the 1 in source view.
Why does this control "lose" the views?
Init code:
protected void Page_Load(object sender, EventArgs e)
{
if (Request.QueryString == null || Request.QueryString.Count < 1)
Response.Redirect(Server.MapPath("~/Packages/"));
if (!Page.IsPostBack)
{
if (Request.QueryString["id"].ToString() == string.Empty)
Response.Redirect(Server.MapPath("~/Packages/"));
var id = Server.HtmlEncode(Request.QueryString["id"].ToString());
Guid packID = Guid.Parse(id);
using (var context = new GaleEntities())
{
var thePackage = context.PackageEnts.First(p => p.packageID == packID);
var theVariants = thePackage.Variants;
var mydatasource = new List<PackageEnt> { thePackage };
var myVariantDataSource = new List<Variant>();
foreach (Variant single in theVariants)
{
myVariantDataSource.Add(single);
}
packageForm.DataSource = mydatasource;
variantRepeat.DataSource = myVariantDataSource;
RenderProductGridviews(theVariants);
prodView.SetActiveView(prodView.Views[0]);
}
packageForm.DataBind();
variantRepeat.DataBind();
Page.DataBind();
}
}
protected void RenderProductGridviews(System.Data.Objects.DataClasses.EntityCollection<Variant> variantCol)
{
foreach (Variant packVar in variantCol)
{
View newView = new View();
GridView prodGrid = new GridView();
var myProdDataSource = new List<vw_VariantProduct>();
using (var context = new GaleEntities())
{
var singleProd1 = context.vw_VariantProduct.Where(vp => vp.variantID == packVar.variantID);
foreach (vw_VariantProduct extProd in singleProd1)
{
myProdDataSource.Add(extProd);
}
}
prodGrid.DataSource = myProdDataSource;
BoundField _column = new BoundField();
_column.DataField = "product_title";
_column.HeaderText = "Product";
prodGrid.Columns.Add(_column);
_column = new BoundField();
_column.DataField = "product_title";
_column.HeaderText = "Product";
prodGrid.Columns.Add(_column);
_column = new BoundField();
_column.DataField = "product_desc";
_column.HeaderText = "Description";
prodGrid.Columns.Add(_column);
_column = new BoundField();
_column.DataField = "product_time";
_column.HeaderText = "Time (mins)";
prodGrid.Columns.Add(_column);
_column = new BoundField();
_column.DataField = "quantity";
_column.HeaderText = "Quantity";
prodGrid.Columns.Add(_column);
prodGrid.DataBind();
newView.ID = packVar.variantID.ToString();
newView.Controls.Add(prodGrid);
prodView.Views.Add(newView);
}
}
Now, as usual almost all questions with the dynamic controls in ASP.Net words share the same common problem...
You need to create the dynamic controls on every post, you are only creating them the first time the page is loaded. Follow this simple rules:
Dynamic controls should be created in the PreInit event when you are not working with a master page, if you are, then create the controls in the Init event
Avoid setting properties that can be changed in each post in these events because when the view state is applied (in a post event) the properties will be overridden
Dynamic controls must be created every time the page is posted, avoid this if(!this.IsPostBack) this.CreatemyDynamicControls();
When you create the controls in the PreInit or Init events, their states will be automatically set in a post event, which means in the LoadComplete event your controls will contain their state back even when you create them again in each post and even when you did not explicitly set their state. Note this behavior is different when you are dealing with controls created at design time, in that case, the event where the state has been set is the Load event
Event subscription should occur before the PageLoadComplete or they will not be raised
I have posted several answers about dynamic controls:
https://stackoverflow.com/a/11127064/1268570
https://stackoverflow.com/a/11167765/1268570
Click events on Array of buttons
Button array disappears after click event
Dynamically create an ImageButton
This piece of code creates dynamic controls on-demand, and each control keeps its state on each post
public partial class DynamicControlsOnDemand : System.Web.UI.Page
{
public int NumberOfControls
{
get
{
if (this.ViewState["d"] == null)
{
return 0;
}
return int.Parse(this.ViewState["d"].ToString());
}
set
{
this.ViewState["d"] = value;
}
}
protected void Page_PreLoad(object sender, EventArgs e)
{
this.CreateDynamicControls();
}
protected void addControl_Click(object sender, EventArgs e)
{
this.NumberOfControls = this.NumberOfControls + 1;
this.myPanel.Controls.Add(this.CreateTextbox(this.NumberOfControls));
}
private void CreateDynamicControls()
{
for (int i = 0; i < this.NumberOfControls; i++)
{
var t = this.CreateTextbox(i + 1);
t.TextChanged += (x, y) => this.lblMessage.Text += "<br/>" + (x as TextBox).ID + " " + (x as TextBox).Text;
this.myPanel.Controls.Add(t);
}
}
private TextBox CreateTextbox(int index)
{
var t = new TextBox { ID = "myTextbox" + index.ToString(), Text = "de" };
return t;
}
}
ASPX
<asp:Panel runat="server" ID="myPanel">
</asp:Panel>
<asp:Button Text="Add Control" runat="server" ID="addControl" OnClick="addControl_Click" />
<asp:Label ID="lblMessage" runat="server" />
Output
You first code block where you are setting the active View is based on an ItemCommand event, so I'm assuming this fires during a PostBack?
Your code which adds the additional views within Page_Load is only running if not a post back. Try removing the conditional if(!Page.IsPostBack) statement. You need to add dynamic controls on every page lifecycle.