Multiview has Views added programmatically disappear when trying to change view - c#

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.

Related

Maintain State of Dynamically Added DropDownList c#

I was hoping someone could provide some advice on what I am doing wrong here. I am attempting to dynamically add a series of DropDownList controls that will be populated from the database. I have many other DropDownLists added at design time that are populating from the database and maintaining state across postbacks.
I am only experiencing issues with the dynamically added controls. The issue is that the DropDown control is populating from the database when initially created and is returning empty on postback. (I have set autopostback to true for the DropDownList control so that postback occurs when selected item changes.)
I have read a number of posts and attempted a variety of strategies and nothing has worked so far.
Here is the relevant code:
I have a placeholder to attach the control to.
<asp:PlaceHolder ID="DynamicControlsHolder" runat="server" />
I use a session variable to hold the number of controls (for my test I am only adding 1 but will need to add several)
public int NumberOfControls
{
get { return (int)ViewState["NumControls"]; }
set { ViewState["NumControls"] = value; }
}
I call two different methods depending upon whether it is a postback or not.
if (!IsPostBack)
{
this.NumberOfControls = 0;
addSomeControls();
}
else
{
this.createControls();
}
protected void addSomeControls() //done in original page_load so bind data
{
DropDownList dl = new DropDownList();
//not using the following event handler yet, so I didn't post the code
dl.SelectedIndexChanged += new EventHandler(dlOnSelectedIndexChange);
using (I.DBEntities1 ctx = new I.IDBEntities1())
{
dl.EnableViewState = true;
dl.AutoPostBack = true;
dl.ID = "ControlID_" + NumberOfControls.ToString();
dl.DataSource = ctx.Lk_PersonPersonAssocType.OrderBy(c => c.Assoc_Type);
dl.DataValueField = "ID";
dl.DataTextField = "Assoc_Type";
dl.DataBind();
}
DynamicControlsHolder.Controls.Add(dl);
this.NumberOfControls++;
}
protected void createControls() //postback
{
int count = this.NumberOfControls;
for (int i = 0; i < count; i++)
{
DropDownList dl = new DropDownList();
dl.ID = "ControlID_" + NumberOfControls.ToString();
DynamicControlsHolder.Controls.Add(dl);
}
}
Any assistance would be greatly appreciated.
I now have things working and wanted to post the answer in the event this it will assist others. #dricdar, thanks for your help. Aspects of your feedback assist in solving the problem.
I moved the call to createControls() into OnInit.
I changed NumberOfControls to a session variable:
public int NumberOfControls
{
get { return (int)Session["NumControls"]; }
set { Session["NumControls"] = value; }
}
In OnInit, onPostBack I call createControls().
In Page_Load, !isPostBack, I set NumberOfControls to zero and call addSomeControls();
The methods now look as follows;
protected void addSomeControls() //done in original page_load so bind data
{
DropDownList dl = new DropDownList();
dl.SelectedIndexChanged += new EventHandler(dlOnSelectedIndexChange);
dl.EnableViewState = true;
dl.AutoPostBack = true;
this.NumberOfControls++;
dl.ID = "ControlID_" + this.NumberOfControls.ToString();
using (I.DBEntities1 ctx = new I.DBEntities1())
{
dl.DataSource = ctx.Lk_PersonPersonAssocType.OrderBy(c => c.Assoc_Type);
dl.DataValueField = "ID";
dl.DataTextField = "Assoc_Type";
dl.DataBind();
}
DynamicControlsHolder.Controls.Add(dl);
DynamicControlsHolder.EnableViewState = true;
}
protected void createControls() //postback, rely upon viewstate here
{
int count = this.NumberOfControls;
for (int i = 0; i < count; i++)
{
DropDownList dl = new DropDownList();
dl.SelectedIndexChanged += new EventHandler(dlOnSelectedIndexChange);
dl.AutoPostBack = true;
using (I.DBEntities1 ctx = new I.DBEntities1())
{
dl.DataSource = ctx.Lk_PersonPersonAssocType.OrderBy(c => c.Assoc_Type);
dl.DataValueField = "ID";
dl.DataTextField = "Assoc_Type";
dl.DataBind();
}
dl.ID = "ControlID_" + NumberOfControls.ToString();
DynamicControlsHolder.Controls.Add(dl);
}
}

How to execute a class once and use the data in ASP.net page

I have the following class (UCNewWorkFlow) which calls a cache database and retrieves rows and adds it to a string array:
public partial class UCNewWorkflow : System.Web.UI.Page
{
private string Connectioncacha = "";
public UCNewWorkflow()
{
int temp;
if (IsItWorkDay(DateTime.Now))
{
temp = 21;
}
else
{
temp = 17;
}
try
{
CacheConnection CacheConnect = new CacheConnection();
CacheConnect.ConnectionString = Connectioncacha;
CacheConnect.Open();
String SQLtext = #"";
DataTable table = new DataTable();
CacheCommand Command = new CacheCommand(SQLtext, CacheConnect);
CacheDataReader Reader = Command.ExecuteReader();
string[] inArr = new string[4];
int k = 0;
if (Reader.HasRows)
{
while (Reader.Read())
{
inArr[k] = Reader["NotYetSeen"].ToString();
returnTime(Convert.ToInt32(inArr[k]));
k++;
}
}
}
catch (Exception ce)
{
}
}
public string returnTime(int inHowMany)
{
string strTime = "";
double future = 0;
DateTime dt = DateTime.Now;
if (inHowMany / 2.0 <= 1)
{
strTime = "15 mins";
}
else if (inHowMany == 0)
{
strTime = "<15 mins";
}
else if (inHowMany / 2.0 > 1)
{
future = Math.Ceiling((inHowMany / 2.0)) * 15;
DateTime tempdate = dt.AddMinutes(future);
TimeSpan result = tempdate - DateTime.Now;
strTime = ToReadableString(result);
}
return strTime;
}
}
The result of the SQL query:
I have the following labels in my ASP.net page:
<asp:Label ID="lblFirstRow" runat="server" Text="Label"></asp:Label>
<asp:Label ID="lblSecondRow" runat="server" Text="Label"></asp:Label>
<asp:Label ID="lblThirdRow" runat="server" Text="Label"></asp:Label>
<asp:Label ID="lblFourthRow" runat="server" Text="Label"></asp:Label>
The code-behind for the ASP.net page:
protected void Page_Load(object sender, EventArgs e)
{
UCNewWorkflow uc = new UCNewWorkflow();
}
At the moment, I can't access the label from the class file.
How can I modify the code so, I have to call the class once and it will populate all four labels.
You are trying to perform this database query during the page's constructor, so it is too early in the ASP.NET Web Forms page lifecycle to have access to those arrays. Those labels do not exist when your constructor is called; they are created during the page initialization event.
As NicoTek suggested, using the Page_Load event handler is a good way of updating these labels. However, if you do it his way, I do not see a reason why your class is inheriting from System.Web.UI.Page, I would recommend refactoring your code so that this and any other database operations exist in another class. This will allow you to reuse code and prevent clutter and repetition in your code-behind files.
It looks to me that you want to return the string array inArr as a property of your UCNewWorkflow class and then bind this to a repeater on the Page_Load of your code-behind as suggested by #NicoTek.
Your Repeater definition on the code-in-front should contain just one Label definition and then as data is bound to the Repeater a new instance of the label is created for each element in your string array.
More details on repeaters can be found at
http://www.w3schools.com/aspnet/aspnet_repeater.asp
you could do
protected void Page_Load(object sender, EventArgs e)
{
UCNewWorkflow uc = new UCNewWorkflow();
lblFirstRow.Text = "someString"
}

Maintaning my choices on GridView Checkbox

I have this Module in my project in which I have 2 gridviews. One is for the Main MenuModule and the other one is for it's subMenu. I created a List so that when a row on my Main Menu Module has been checked and it has a corresponding submenu, it will show on the SubMenu Gridview.
Now, I can see my SubMenuGridview when I get back to that page (I used session), but I noticed that the checkbox I ticked were all gone.
My problem was on how can my page remember the checkboxes I checked, both from my Main Menu Module gridview and from my Submenu gridview.
protected void cbxSelect_CheckedChanged(object sender, EventArgs e)
{
SubMenuGrid.DataSource = null;
SubMenuGrid.DataBind();
Business.SubMenuModules sub = new Business.SubMenuModules();
List<oSubList> oList = new List<oSubList>();
int counter = 0;
foreach (GridViewRow nRow in gvModuleList.Rows)
{
Int32 intModID = Convert.ToInt32(nRow.Cells[0].Text);
CheckBox chkBx = (CheckBox)nRow.FindControl("cbxSelect");
if (chkBx.Checked == true)
{
counter = counter + 1;
var oModList = sub.GetAllMenuPerModuleID(intModID);
if (oModList.Count > 0)
{
foreach (var rec in oModList)
{
oSubList olist = new oSubList
{
ID = rec.ID,
ModuleID = rec.ModuleID,
Submenu = rec.Submenu,
Description = rec.Description
};
oList.Add(olist);
}
Session["list"]=oList;
SubMenuGrid.DataSource = oList;
SubMenuGrid.DataBind();
}
}
}
}
This can be done using:
ViewState
SessionPageStatePersister
Custom Session based solution
For view state-see the below posted link in comments..
Custom Session based solution
We are going to use the pre render method.
This method is being invoked after the page has been initialized but before it saved its ViewState and rendered.
Are are going to load the Request.Form into a session variable and load it back with each call to the page that is not a postback.
protected void Page_PreRender(object sender, EventArgs e)
{
if (!Page.IsPostBack && Session["PageState"] != null)
{
NameValueCollection formValues = (NameValueCollection)Session["PageState"];
String[] keysArray = formValues.AllKeys;
for (int i = 0; i < keysArray.Length; i++)
{
Control currentControl = Page.FindControl(keysArray[i]);
if (currentControl != null)
{
if (currentControl.GetType() == typeof(System.Web.UI.WebControls.TextBox)) ((TextBox)currentControl).Text = formValues[keysArray[i]];
else if (currentControl.GetType() == typeof(System.Web.UI.WebControls.CheckBox))
{
if (formValues[keysArray[i]].Equals("on")) ((CheckBox)currentControl).Checked = true;
}
else if (currentControl.GetType() == typeof(System.Web.UI.WebControls.DropDownList))
((DropDownList)currentControl).SelectedValue = formValues[keysArray[i]].Trim();
}
}
}
if(Page.IsPostBack) Session["PageState"] = Request.Form;
}
SessionPageStatePersister
The abstract PageStatePersister class represents the base class that encapsulates the Page State storage and processing.
Storage can be done with the default HiddenFieldPageStatePersister class or with SessionPageStatePersister.
When SessionPageStatePersister is used, the .NET Server manages the _VIEWSTATE in a session object instead of a hidden field on your form.
Changing the state storage looks like this:
protected override PageStatePersister PageStatePersister
{
get
{
return new SessionPageStatePersister(this);
}
}

Gridview Edit/Update is not working?

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.

postback doesnt refresh contents of testbox or gridview

I realy need help for this. I am using AjaxControlToolkit.TabContainer and using ASP.NET Framework 4.0. Gridview,textbox and button are placed in TabContainer on asp page. When I press button postback does happen but its not binding gridview to datatable and textbox contents are also not updated.
I debug the code and found when i press button postback does happen and content does fill up in gridview and textbox value also assigned with new value. but values doesnt display on the page. I dont know why its happening. please help.
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
if (ListBoxCustomer.Items.Count != 0)
{
int[] _selectedItems = ListBoxCustomer.GetSelectedIndices();
string _comma = "";
string _custID = "";
InitializeConnection();
if (_selectedItems.Length != 0)
{
foreach (int i in _selectedItems)
{
_custID = _custID + _comma + ListBoxCustomer.Items[i].Value;
_comma = ",";
}
if (custObj != null)
{
//DataTable _dt = new DataTable();
DataSet _ds = new DataSet();
GridViewCustomer.Visible = true;
GridViewCustomer.AutoGenerateColumns = true;
_ds = custObj.GetSelectedCustomers(1, _custID);
GridViewCustomer.DataSource = _ds.Tables[0];
GridViewCustomer.DataBind();
TextBoxTest.Text = GridViewCustomer.Rows.Count.ToString();
TextBoxTest.Text = "test";
}
}
}
}
}
thanks.
Perhaps the DataBind code is never being reached. Have you set some breakpoints to make sure the if-statements aren't blocking you? That is... Is ListBoxCustomer.Items.Count definitely not zero... Is custObj definitely not null?
Where do you assign a value to custObj?

Categories