Dynamic C# Not rendering on page_load - c#

I have a method which is intended to dynamically generate a series of divs based on the entry of a value from a dropdown list. However, I wish to reuse the same code to generate the tables on the first page_load when a number already exists.
This is where the method is called. It is called GenerateTables and it is called from the Page_Load event:
if (!IsPostBack)
{
AcademicProgramme programme;
if (Request.QueryString["id"] != null)
{
programme = academic.GetAcademicProgramme(Request.QueryString["id"]);
programmeName.Text = programme.Name;
PopulateView(programme);
GenerateTables(programme.Levels);
}
}
And here is the method itself (apologies for the size of the method):
private void GenerateTables(int count)
{
for (int i = 1; i < count + 1; i++)
{
LiteralControl title = new LiteralControl();
LiteralControl close = new LiteralControl();
LiteralControl close2 = new LiteralControl();
String script = "<div class=\"ModuleProgTable\"><h3>Level " + i + "</Modules></h3></br>";
title.Text = script;
AcademicTable.Controls.Add(title);
Panel panel = new Panel();
panel.ID = "Level" + i + "Modules";
PopulatePanel(panel, GetModulesSession(i));
Button a = new Button();
a.ID = "AddModule" + i;
a.Text = "Add Module";
a.Click += (OpenPopup);
AcademicTable.Controls.Add(panel);
AcademicTable.Controls.Add(a);
close.Text = "</div> <!-- Close here -->";
close2.Text = "</div>";
AcademicTable.Controls.Add(close);
}
}
The divs are clearly being populated because if I change the dropdown option then they appear on the PostBack without fail. It's when I try to get them to render on the first page_load that I am having problems.
Any feedback and advice would be greatly appreciated!
Regards,
-Michael

Related

ImageButton not firing on the second time

In my ASP.Net page I need to show an HTML div who contains : Images, Text, Arrows and Connectors.
What are my "Connectors" ?
It's an ImageButton, and when the user click on this connector, the HTML div is showing a new content. This connectors are used to navigate in a TreeView.
But my problem is :
I create all my connectors (and all the HTML div content) dynamically. When the user click on the first connector the HTML div is showing new content. But on this second content, when the user click on a connector : nothing. The Click event of the ImageButton is not fired.
This is my Connector creation (on PageLoad and then on each Connector Click) :
List<Connecteur> ListConnecteur = new List<Connecteur>();
ListConnecteur = NomenclatureObj.SelectConnecteurs(DocId, ExterneData.RapidoBDDCnx);
foreach (Connecteur CeConnecteur in ListConnecteur)
{
if (CeConnecteur.FK_docversion_suivant_id != 0)
{
ImageButton ImgBtnTmp = new ImageButton();
ImgBtnTmp.Width = 30;
ImgBtnTmp.Height = 30;
ImgBtnTmp.ImageUrl = "~/images/GreenButton.png";
ImgBtnTmp.Style.Add("left", CeConnecteur.position_x_pix.ToString() + "px");
ImgBtnTmp.Style.Add("top", CeConnecteur.position_y_pix.ToString() + "px");
ImgBtnTmp.Click += new ImageClickEventHandler(ImgBtnTmp_Click);
ImgBtnTmp.CommandArgument = CeConnecteur.FK_docversion_suivant_id.ToString();
ImgBtnTmp.Style.Add("position", "absolute");
DivAffichage.Controls.Add(ImgBtnTmp);
ImgBtnTmp.CausesValidation = true;
}
}
And this is my Connector OnClick :
public void ImgBtnTmp_Click(object sender, EventArgs e)
{
ImageButton ThisBtn = sender as ImageButton;
string CommandArg = ThisBtn.CommandArgument;
int DocId = Convert.ToInt32(CommandArg);
TREEVIEW_NIVEAU++;
//DocId of the clicked connector
Session["DocId"] = DocId;
ClearDiv();
LoadDiv(DocId);
}
EDIT 1 : My whole LoadDiv() function
public void LoadDiv(int DocId)
{
#region Connecteurs
List<Connecteur> ListConnecteur = new List<Connecteur>();
ListConnecteur = NomenclatureObj.SelectConnecteurs(DocId, ExterneData.RapidoBDDCnx);
foreach (Connecteur CeConnecteur in ListConnecteur)
{
if (CeConnecteur.FK_docversion_suivant_id != 0)
{
ImageButton ImgBtnTmp = new ImageButton();
ImgBtnTmp.Width = 30;
ImgBtnTmp.Height = 30;
ImgBtnTmp.ImageUrl = "~/images/GreenButton.png";
ImgBtnTmp.Style.Add("left", CeConnecteur.position_x_pix.ToString() + "px");
ImgBtnTmp.Style.Add("top", CeConnecteur.position_y_pix.ToString() + "px");
ImgBtnTmp.Click += new ImageClickEventHandler(ImgBtnTmp_Click);
ImgBtnTmp.CommandArgument = CeConnecteur.FK_docversion_suivant_id.ToString();
ImgBtnTmp.Style.Add("position", "absolute");
DivAffichage.Controls.Add(ImgBtnTmp);
}
}
#endregion
#region Textes
List<Texte> ListTexte = new List<Texte>();
ListTexte = NomenclatureObj.SelectTextes(DocId, LANGUE_ID, ExterneData.RapidoBDDCnx);
foreach (Texte CeTexte in ListTexte)
{
Label LblText = new Label();
LblText.Text = CeTexte.contenu;
LblText.Width = CeTexte.largeur_voulue_pix;
LblText.Style.Add("left", CeTexte.position_x_pix.ToString() + "px");
LblText.Style.Add("top", CeTexte.position_y_pix.ToString() + "px");
LblText.Style.Add("position", "absolute");
DivAffichage.Controls.Add(LblText);
}
#endregion
#region Images
List<ImageNomenclature> ListImg = new List<ImageNomenclature>();
ListImg = NomenclatureObj.SelectImages(DocId, ExterneData.RapidoBDDCnx);
foreach (ImageNomenclature CetteImage in ListImg)
{
Image ImgTmp = new Image();
ImgTmp.ImageUrl = "~/Nomenclature/RAPIDO/planches/" + CetteImage.fichier_chemin;
ImgTmp.Width = CetteImage.largeur_voulue_pix;
ImgTmp.Height = CetteImage.hauteur_voulue_pix;
ImgTmp.Style.Add("left", CetteImage.position_x_pix.ToString() + "px");
ImgTmp.Style.Add("top", CetteImage.position_y_pix.ToString() + "px");
ImgTmp.Style.Add("position", "absolute");
ImgTmp.Style.Add("z-index", "-1");
DivAffichage.Controls.Add(ImgTmp);
}
#endregion
#region Flèches
List<Fleche> ListFleche = new List<Fleche>();
ListFleche = NomenclatureObj.SelectFleches(DocId, LANGUE_ID, ExterneData.RapidoBDDCnx);
foreach (Fleche CetteFleche in ListFleche)
{
string HTMLCode = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"800\" height=\"600\"><line x1=\"" + CetteFleche.position_x1_pix + "\" y1=\"" + CetteFleche.position_y1_pix + "\" x2=\"" + CetteFleche.position_x2_pix + "\" y2=\"" + CetteFleche.position_y2_pix + "\" stroke=\"#ff0000\"/></svg>";
//DivAffichage.InnerHtml += HTMLCode;
}
#endregion
}
You should create your dynamic control every time on Page_Init or Page_Load if you would like to handle events from them after Postback.
See links below for details:
http://msdn.microsoft.com/en-us/library/y3bwdsh3%28v=vs.140%29.aspx
http://msdn.microsoft.com/en-us/library/hbdfdyh7%28v=vs.100%29.aspx
Here you can see the same problem.
EDIT
Try to do something like this:
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
LoadDiv(Session["DocId"])
}
}

Dynamic Table: Link button to textbox cell by cell

I have a dynamic table, where, on every row I have a text box (txtCantitate) and a button (btnMinus). In the textbox I have quantity (int) and on the button click I want the quantity to decrease by one. Here you have what I have on the table:
Can you help me make the code for the buttons? The problem is that it is a dynamic button... on every record it has the same ID... I don't know how to do it...
My languages used on the project C#, .NET 4.5, js, Jquery.
cell = new HtmlTableCell();
HtmlInputButton btnMinus = new HtmlInputButton();
btnMinus.ID = "btnMinus";
btnMinus.Value = "-";
cell.Controls.Add(btnMinus);
row.Cells.Add(cell);
cell = new HtmlTableCell();
HtmlInputText txtCantitate = new HtmlInputText();
txtCantitate.ID = "txtCantitate";
txtCantitate.Value = publicatie.Cantitate.ToString();
cell.Controls.Add(txtCantitate);
row.Cells.Add(cell);
You need to set a click event on the button, which will perform the action you want:
You will need to set the ID of both the textbox and the button to match the row+cell index you're in first... since these are HtmlControls, you don't really have their index so you'll have to find a way to get these in there somehow (i won't code this for you, sorry).
btnMinus.ID = "btnMinus_" + CurrentRowIndex.ToString() + "_" + CurrentCellIndex.ToString();
txtCantitate.ID = "txtCantitate_" + CurrentRowIndex.ToString() + "_" + CurrentCellIndex.ToString();
then you will have to set the event handler...
server side click event handler setter (see below for actual event handler code):
btnMinus.Click += myButtonClick;
client-side click event handler setter:
btnMinus.Attributes.Add("onclick","JavaScript:myButtonClick(this);");
If you want to do the event handler code server-side:
private void myButtonClick(object sender, EventArgs e)
{
Button tmp = sender as Button;
string[] id = tmp.ID.Split(new string[]{"_"}, StringSplitOptions.None);
string textbox_ID = "txtCantitate" + "_" + id[1] + "_" + id[2];
TextBox txt = this.Controls.FindControl(textbox_ID) as TextBox;
int val = -1;
string finaltext = "";
if(int.TryParse(txt.Text, out val))
finaltext = (val-1).ToString();
else
finaltext = "Invalid number, Cannot decrement!";
txt.Text = finaltext;
}
If you want to do the event handler code client-side:
function myButtonClick(object sender)
{
//i'll let you figure this one out for yourself if you want to do it client-side, but it's very similar to the server-side one as far as logic is concerned...
}
Here is the solution,
Javascript
function MinusVal(ctrl)
{
var TextBox = $(ctrl).parent().next().find("input[type=text]");
var Value = parseInt(TextBox.val());
TextBox.val(Value - 1);
return false;
}
C# Backend
btnMinus.Attributes.Add("onclick", "MinusVal(this);");

Retaining Label and Literal controls after post back fails

I am dealing with a very unusual situation through which made me go through the effort of putting up for some answers.
I am trying to regenerate some controls based on the following document,
http://www.codeproject.com/Articles/3684/Retaining-State-for-Dynamically-Created-Controls-i
This approach works TextBox controls but does not seem to respond to Label, Literal, UploadFile or other controls that I'm not aware of.
I do understand this not working for UploadFile due to security reasons, but why not for other non TextBox controls?
The above article suggests that if we maintain the ID of a control, we can retain them after post back but in the following implementation I only get the TextBox responding to this solution. The "Label" and "Literal" controls in this situation are lost after PostBack which is undesirable given that I pretty much follow the recipe line by line.
Can someone please have a look at the following implementation and see where I'm going wrong or if I got the whole concept wrong in a way?
This is a counter to keep track of the number of control sets generated,
protected int NumberOfControls
{
get { return (int)ViewState["NumControls"]; }
set { ViewState["NumControls"] = value; }
}
This is the Page_Load event that fetches the previous slides from the DB on initial page load and regenerates the same page on Postback. AddSlide is a "Placeholder" control where I post other Controls into.
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
this.NumberOfControls = PopulateCarouselSettingFields(AddSlides);
}
else
{
this.GenerateControls();
}
}
This is the definition for "PopulateCarouselSettingsFields".
public static int PopulateCarouselSettingFields(PlaceHolder _AddSlides)
{
string result = string.Empty;
int counter = 0;
string CS = ConfigurationManager.ConnectionStrings["someconn"].ConnectionString;
using (SqlConnection conn = new SqlConnection(CS))
{
SqlCommand SqlCmd = new SqlCommand();
conn.Open();
SqlCmd.Connection = conn;
SqlCmd.CommandType = CommandType.StoredProcedure;
SqlCmd.CommandText = "storedprocedure";
SqlDataReader dReader;
dReader = SqlCmd.ExecuteReader();
while (dReader.Read())
{
Literal lit1 = new Literal();
lit1.ID = "Lit1_" + counter;
lit1.Text = "<div class=\"controls controls-row\"><div class=\"span3\">";
_AddSlides.Controls.Add(lit1);
Label CarouselTextLabel = new Label();
CarouselTextLabel.ID = "CarouselTextLabel" + counter;
CarouselTextLabel.Text = "Carousel Text";
CarouselTextLabel.Font.Bold = true;
CarouselTextLabel.CssClass = "control-label";
_AddSlides.Controls.Add(CarouselTextLabel);
TextBox CarouselText = new TextBox();
CarouselText.ID = "CarouselText" + counter;
CarouselText.TextMode = TextBoxMode.MultiLine;
CarouselText.Height = 50;
CarouselText.Text = dReader["CarouselText"].ToString();
_AddSlides.Controls.Add(CarouselText);
Literal Lit2 = new Literal();
Lit5.ID = "Lit2_" + counter;
Lit5.Text = "</div></div></div><br />";
_AddSlides.Controls.Add(Lit2);
counter++;
}
}
return counter;
}
This is supposed to regenerate or re-state all the controls using their IDs upon PostBack called from Page_Load event.
protected void GenerateControls()
{
int count = this.NumberOfControls;
for (int i = 0; i < count; i++)
{
Literal lit1 = new Literal();
lit1.ID = "Lit1_" + i.ToString();
AddSlides.Controls.Add(lit1);
Label CarouselTextLabel = new Label();
CarouselTextLabel.ID = "CarouselTextLabel" + i.ToString();
AddSlides.Controls.Add(CarouselTextLabel);
TextBox CarouselText = new TextBox();
CarouselText.ID = "CarouselText" + i.ToString();
AddSlides.Controls.Add(CarouselText);
Literal Lit2 = new Literal();
Lit2.ID = "Lit2_" + i.ToString();
AddSlides.Controls.Add(Lit2);
}
}
The following piece of code adds new set of controls to the Placeholder "AddSlides" container.
protected void AddMoreSlidesToCarousel(object sender, EventArgs e)
{
Literal lit1 = new Literal();
lit1.ID = "Lit1_" + NumberOfControls.ToString();
lit1.Text = "<div class=\"controls controls-row\"><div class=\"span3\">";
AddSlides.Controls.Add(lit1);
Label CarouselTextLabel = new Label();
CarouselTextLabel.ID = "CarouselTextLabel" + NumberOfControls.ToString();
CarouselTextLabel.Text = "Carousel Text";
CarouselTextLabel.Font.Bold = true;
CarouselTextLabel.CssClass = "control-label";
AddSlides.Controls.Add(CarouselTextLabel);
TextBox CarouselText = new TextBox();
CarouselText.ID = "CarouselText" + NumberOfControls.ToString();
CarouselText.TextMode = TextBoxMode.MultiLine;
CarouselText.Height = 50;
AddSlides.Controls.Add(CarouselText);
Literal Lit2 = new Literal();
Lit2.ID = "Lit2_" + NumberOfControls.ToString();
Lit2.Text = "</div></div></div><br />";
AddSlides.Controls.Add(Lit2);
this.NumberOfControls++;
}
I'm sorry to put it like this, but the article you are relying on is doing it wrong.
Dynamically created controls MUST be created in Page_Init, so that they exist before any ViewState stuff. Also, dynamically controls must be recreated each and every time the Page is initialized, PostBack or not.
ViewState/PostBack do not "retain" controls, only the state of such controls.
Please read this article: ASP.NET Page Life Cycle Overview

Add Ajax CalendarExtender to a dynamic textBox in ASP.NET C#

Is there a way to add Ajax CalendarExtender to a dynamic ASP.NET textbox control? Basically I'm trying to do the following:
protected void Page_Load(object sender, EventArgs e)
{
database.DB myDB = new database.DB();
DataTable myVars = new DataTable();
string myTopicID = (string)Session["myTopicID"];
bool myInvite = (bool)Session["myInvite"];
bool mySig = (bool)Session["mySig"];
string myLogo = (string)Session["myLogo"];
string myImage = (string)Session["myImage"];
string myLanguage = (string)Session["myLanguage"];
myVars = myDB.getVarFields(myTopicID, myLanguage);
AjaxControlToolkit.CalendarExtender calenderDate = new AjaxControlToolkit.CalendarExtender();
for (int i = 0; i < myVars.Rows.Count; i++)
{
Label label = new Label();
TextBox text = new TextBox();
label.Text = Convert.ToString(myVars.Rows[i]["varName"]);
myPlaceHolder.Controls.Add(label);
text.ID = Convert.ToString(myVars.Rows[i]["varName"]);
myPlaceHolder.Controls.Add(new LiteralControl(" "));
myPlaceHolder.Controls.Add(text);
if (Convert.ToString(myVars.Rows[i]["varName"]).Contains("Date:"))
{
calenderDate.TargetControlID = "ContentPlaceHolder1_" + text.ID;
myPlaceHolder.Controls.Add(calenderDate);
}
myPlaceHolder.Controls.Add(new LiteralControl("<br />"));
}
}
The error I get when I run the code above is the following:
The TargetControlID of '' is not valid. A control with ID 'ContentPlaceHolder1_Date:' could not be found.
Which makes sense I suppose since the actual text box does not exist yet. But is there a way around this?
I think ASP.NET will be smart enough to handle it if you just use text.ID, you shouldn't need to add the ContentPlaceHolder1_ prefix.
If that doesn't work, you can use the TextBox' ClientIdMode property to set it to static, then text.ID will definitely work.
The following code worked locally for me:
AjaxControlToolkit.CalendarExtender calenderDate = new AjaxControlToolkit.CalendarExtender();
for (int i = 0; i < 2; i++)
{
Label label = new Label();
TextBox text = new TextBox();
label.Text = Convert.ToString("varName");
ph1.Controls.Add(label);
text.ID = "myId" + i;
ph1.Controls.Add(new LiteralControl(" "));
ph1.Controls.Add(text);
calenderDate.TargetControlID = text.ID;
ph1.Controls.Add(calenderDate);
ph1.Controls.Add(new LiteralControl("<br />"));
}
Only differences I think you may want to investigate: I'm using latest ControlToolkit from Nuget, I'm using a ToolkitScriptManager instead of default ScriptManager. One thing that may be important to you is making sure you make text.ID unique.

Click Event for Dynamically Generate Linkbutton

i created a simple registration page which have fields Name,Username and Password.. actually am checking the username with database whether that username already had or not...
suppose if that username already taken,then i display"Username Already Taken" message in label,and also i create dynamically 4 link buttons for username suggestions like
now when i click on linkbuttons,that are bind to username textbox.. here is my code
give me some idea how to bind that linkbutton to textbox..
You should minimize server requests from client, especially if you want to update UI controls. I suggest to use java script to update text box with new value.
for (int i = 0; i < 4; i++)
{
LinkButton lbtn = new LinkButton();
lbtn.OnClientClick = "document.getElementById('" + txtuname.ClientID + "').value = '"+txtuname.Text + i+"'; return false;";
lbtn.Text = txtuname.Text + i;
phlinks.Controls.Add(lbtn);
phlinks.Controls.Add(new LiteralControl(" "));
}
Try this
for (int i = 0; i < 4; i++)
{
LinkButton lbtn = new LinkButton();
lbtn.OnClientClick = "document.getElementById('" + txtuname.ClientID + "').value = this.innerText; return false;";
lbtn.Text = i.ToString();
phlinks.Controls.Add(lbtn);
}

Categories