Scope of a LiteralControl problem - c#

I have a piece of code that creates dynamic controls using 2 while loops.
As you can see, I am forced to declare both LiteralControls INSIDE each while loop because if I don't, the puBugList.Controls.Add(lineBreak) will not acknowledge.
Q: Why can I not see the scope of the controls from inside a while loop?
//this control is not acknowledged
//LiteralControl lineBreak = new LiteralControl("<br/>");
while (nwReader.Read())
{
int id = (int)nwReader["bid"];
string user = (string)nwReader["buname"];
string prob = (string)nwReader["bproblem"];
string content = id + ". " + user + ": " + prob + "<br/>";
Label lb = new Label();
lb.Text = content;
phBugList.Controls.Add(lb);
//forced to declare 1 here
LiteralControl lineBreak = new LiteralControl("<br/>");
String sqlSelRep = "SELECT * FROM [reply] WHERE bid=#bid";
SqlCommand cmdSelRep = new SqlCommand(sqlSelRep, conn);
cmdSelRep.Parameters.AddWithValue("#bid", id);
SqlDataReader repReader = cmdSelRep.ExecuteReader();
while (repReader.Read())
{
//forced to declare another
LiteralControl lineBreak2 = new LiteralControl("<br/>");one here
string msg = (string)repReader["rmsg"];
Label lbRep = new Label();
lbRep.Text = "Admin: \"" + msg + "\"";
phBugList.Controls.Add(lbRep);
phBugList.Controls.Add(lineBreak2);
}
repReader.Close();
if (Convert.ToInt32(Session["user"]) == 1)
{
phBugList.Controls.Add(lineBreak);
TextBox tbRep = new TextBox();
tbRep.ID = "tb" + id.ToString();
phBugList.Controls.Add(tbRep);
LinkButton butRep = new LinkButton();
butRep.ID = "rep" + id.ToString();
butRep.Text = " Reply";
butRep.Click += InsertReply;
phBugList.Controls.Add(butRep);
LinkButton butDel = new LinkButton();
butDel.ID = "del" + id.ToString();
butDel.Text = " Delete";
butDel.Click += DeleteBug;
phBugList.Controls.Add(butDel);
phBugList.Controls.Add(lineBreak);
}
phBugList.Controls.Add(lineBreak);
}

I think you'r problem is that if you instantiate LiteralControl outside the while loop you are effectively using the same object throughout your code, and you cannot add the same control twice to a Controls collection of another control.
Try the following:
LiteralControl lineBreak = null;
(...)
while (repReader.Read())
{
literalControl = new LiteralContro(...);
}
Anyway, unless you need lineBreak in scope outside the while loop there is nothing wrong declaring the variable inside the loop so your code is perfectly fine.

Related

How to add trigger dynamically to controls that are created dynamically

I have created a bunch of html element programatically in asp.net webforms and I have an UpdatePanel on my aspx page. Now I want to add triggers for every element's click event that are created.
Here is my code
string content = "";
int i = 1000;
string btnRight = "";
string btnLeft = "";
GroupsRepository gr = new GroupsRepository();
List<Group> groups = new List<Group>();
groups = gr.LoadListAllGroups();
foreach (Group gp in groups)
{
btnLeft = "<button class='btnLeftService' runat='server' value='مقالات' />";
btnRight = "<button class='btnRightService' id='" + gp.GroupID.ToString() + "' runat='server' onserverclick='subGroups_ServerClick' value='زیر گروه ها' />";
content += "<div class='item'>";
content += "<div class='row m0 service '><div class='row m0 innerRow item'><div><i class='fa fa-laptop'></i><div class='serviceName'>" + gp.Title + "</div></div><div class='item-overlay left'><ul><li class='liLeft'>" + btnLeft + "</li><li class='liRight'>" + btnRight + "</li></ul></div></div></div>";
i++;
}
ourServises.InnerHtml = content;
GroupsRepository gr = new GroupsRepository();
List<Group> groups = new List<Group>();
groups = gr.LoadListAllGroups();
foreach (Group gp in groups)
{
AsyncPostBackTrigger trigger = new AsyncPostBackTrigger();
trigger.ControlID = gp.GroupID.ToString();
trigger.EventName = "Click";
updatepanel2.Triggers.Add(trigger);
}
but at runtime, I get this error:
A control with ID '1' could not be found for the trigger in UpdatePanel 'updatepanel2'.
What should I do?

Dynamically Create Controls Based Off Data Returned From Query

I am querying access table and with my data that is returned I need to be able to create controls. Now the problem with my code is (I obviously need to learn about loops better than I do) the code executes exactly as it should it does the 1st foreach loop then moves to the 2nd foreach loop. So I have all the labels - then I have all the text boxes. I need it to be a 1 to 1 relationship. So Label Text box. This is my current code that is not producing the desired outcome. Can someone assist me in tweaking this to produce the desired outcome of a 1 to 1 relationship of label to textbox
System.Collections.Hashtable lookup = new System.Collections.Hashtable();
OleDbConnection olecon = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + oName);
olecon.Open();
OleDbCommand command = new OleDbCommand("Query Data Goes Here", olecon);
OleDbCommand command1 = new OleDbCommand("Query Data Goes Here", olecon);
dr = command.ExecuteReader();
while (dr.Read())
{
labelNames.Add(dr[0].ToString());
}
dr.Close();
dr = command1.ExecuteReader();
while (dr.Read())
{
textboxNames.Add(dr[0].ToString());
}
dr.Close();
foreach (string label in labelNames)
{
Label lbl = new Label();
lbl.Name = "lbl_" + index;
lbl.Text = label;
lbl.AutoSize = true;
Form1.Controls.Add(lbl);
index++;
}
foreach (string textbox in textboxNames)
{
TextBox tbx = new TextBox();
tbx.Name = "txt_" + counter;
tbx.AutoSize = true;
Form1.Controls.Add(tbx);
counter++;
}
I don't see any use of textboxNames collection. What you need is, group the two foreach and create label and textbox together and add them to your Form like below
foreach (string label in labelNames)
{
Label lbl = new Label();
lbl.Name = "lbl_" + index;
lbl.Text = label;
lbl.AutoSize = true;
Form1.Controls.Add(lbl);
TextBox tbx = new TextBox();
tbx.Name = "txt_" + index;
tbx.AutoSize = true;
Form1.Controls.Add(tbx);
index++;
}
Rather than doing them as 2 separate foreach loops you could do it in a single for loop, e.g. (assuming labelNames and textboxNames are List<string>):
for (int i = 0; i < labelNames.Count; i++)
{
Label lbl = new Label();
lbl.Name = "lbl_" + labelNames[i];
lbl.Text = labelNames[i];
lbl.AutoSize = true;
Form1.Controls.Add(lbl);
TextBox tbx = new TextBox();
tbx.Name = "txt_" + textboxNames[i];
tbx.AutoSize = true;
Form1.Controls.Add(tbx);
}
Might also be worth checking there are equal numbers of each first as a sanity check:
if (labelNames.Count != textboxNames.Count)
{
//throw exception etc.
}
Replace your two foreach loops with a single for loop that iterates through both lists at the same time.:
for(int i = 0; i < Math.Min(labelNames.Length, textboxNames.Length); i++)
{
Label lbl = new Label();
lbl.Name = "lbl_" + i;
lbl.Text = textboxNames[i];
lbl.AutoSize = true;
Form1.Controls.Add(lbl);
TextBox tbx = new TextBox();
tbx.Name = "txt_" + i;
tbx.AutoSize = true;
Form1.Controls.Add(tbx);
}
The "Math.Min(labelNames.Length, textboxNames.Length)" comparator will make sure the loop stops after whichever list has the fewest entries. I didn't see either of your labelNames or textboxNames collections defined so I'm not sure whether they're arrays or lists or what, so you may need to change "Length" to "Count".

Multiple controls with the same ID 'ddl_Weight' were found. FindControl requires that controls have unique IDs

I am having this error: Multiple controls with the same ID 'ddl_Weight' were found. Find-control requires that controls have unique IDs. thus i am not add to add more objective text-box, drop-down list.
I have to add objectives, drop-down list for weightage and achieved.
private List<DropDownList> inputDropDownList;
private List<DropDownList> inputDropDownList2;
protected void btn_AddObjectives_Click(object sender, EventArgs e)
{
int rowCount = 0;
//initialize a session.
rowCount = Convert.ToInt32(Session["clicks"]);
rowCount++;
//In each button click save the numbers into the session.
Session["clicks"] = rowCount;
//Create the textboxes and labels each time the button is clicked.
for (int i = 0; i < rowCount; i++)
{
TextBox TxtBoxO = new TextBox();
TxtBoxO.TextMode = TextBoxMode.MultiLine;
DropDownList DDLW = new DropDownList();
DropDownList DDLA = new DropDownList();
inputDropDownList = new List<DropDownList>();
inputDropDownList2 = new List<DropDownList>();
Label lblO = new Label();
Label lblW = new Label();
Label lblA = new Label();
TxtBoxO.ID = "TextBoxO" + i.ToString();
DDLW.ID = "DDLW" + i.ToString();
DDLA.ID = "DDLA" + i.ToString();
inputDropDownList.Add(DDLW);
inputDropDownList2.Add(DDLA);
TxtBoxO.Width = 325;
DDLW.Height = 25;
DDLA.Height = 25;
DDLA.ID = "ddl_Achieved";
DDLA.Items.Add("Select");
DDLA.Items.Add("5");
DDLA.Items.Add("10");
DDLA.Items.Add("15");
DDLA.Items.Add("20");
DDLA.Items.Add("25");
DDLA.Items.Add("30");
DDLA.Items.Add("35");
DDLA.Items.Add("40");
DDLA.Items.Add("45");
DDLA.Items.Add("50");
DDLA.Items.Add("55");
DDLA.Items.Add("60");
DDLA.Items.Add("65");
DDLA.Items.Add("70");
DDLA.Items.Add("75");
DDLA.Items.Add("80");
DDLA.Items.Add("85");
DDLA.Items.Add("90");
DDLA.Items.Add("95");
DDLA.Items.Add("100");
DDLW.ID = "ddl_Weight";
DDLW.Items.Add("Select");
DDLW.Items.Add("5");
DDLW.Items.Add("10");
DDLW.Items.Add("15");
DDLW.Items.Add("20");
DDLW.Items.Add("25");
DDLW.Items.Add("30");
DDLW.Items.Add("35");
DDLW.Items.Add("40");
DDLW.Items.Add("45");
DDLW.Items.Add("50");
DDLW.Items.Add("55");
DDLW.Items.Add("60");
DDLW.Items.Add("65");
DDLW.Items.Add("70");
DDLW.Items.Add("75");
DDLW.Items.Add("80");
DDLW.Items.Add("85");
DDLW.Items.Add("90");
DDLW.Items.Add("95");
DDLW.Items.Add("100");
lblO.ID = "LabelO" + i.ToString();
lblW.Text = "LabelW" + i.ToString();
lblA.ID = "LabelA" + i.ToString();
lblO.Text = "Objective " + " " + (i + 1).ToString() + " : ";
lblW.Text = " Weightage" + " " + (i + 1).ToString() + " : ";
lblA.Text = " Achieved " + " " + (i + 1).ToString() + " : ";
//Add the labels and textboxes to the Panel.
Panel1.Controls.Add(lblO);
Panel1.Controls.Add(TxtBoxO);
Panel1.Controls.Add(lblW);
Panel1.Controls.Add(DDLW);
Panel1.Controls.Add(lblA);
Panel1.Controls.Add(DDLA);
}
The error is pretty clear. You're adding multiple controls with the same ID, which is disallowed. Note that you're in a loop:
for (int i = 0; i < rowCount; i++)
We'll assume that rowCount is greater than 1 and that the loop iterates more than once. Within that loop you create controls:
DropDownList DDLW = new DropDownList();
DropDownList DDLA = new DropDownList();
And you assign IDs to them:
DDLW.ID = "DDLW" + i.ToString();
DDLA.ID = "DDLA" + i.ToString();
These IDs are probably unique. But then you overwrite them with ones that are not unique:
DDLA.ID = "ddl_Achieved";
DDLW.ID = "ddl_Weight";
And then you add them to the page:
Panel1.Controls.Add(DDLW);
Panel1.Controls.Add(DDLA);
The purpose of an ID, as its name suggests, is to uniquely identify an object. Just like with id attributes in HTML, if you re-use the same one multiple times in a page then the behavior becomes undefined. The system (in this case wherever you're using FindControl()) expects there to be 0 or 1 elements with any given ID value. You've created more then 1, which is invalid.
You can probably just remove the lines where you set the non-unique IDs and keep the lines where you set the unique ones.

Add textbox via dynamic imagebutton in a panel

I have a problem I seem to stumble over all the time, I have a Drop Down box and you can select a number which creates x number of textboxes with images buttons its for a survey it the image buttons are used to create "Sub-Answers" so they can have answers to answers so my question is I need to when they hit the image button to create a textbox under the orginal textbox here is the code.
for (Int32 i = 1; i <= NumberOfAnwsers; i++)
{
Literal l1 = new Literal();
l1.Text = "<tr><td>Answer " + i + " text.</td><td>";
TextBox tb = new TextBox();
tb.ID = "TextBoxAnswer" + i;
tb.EnableViewState = false;
tb.Width = 300;
Literal l3 = new Literal();
l3.Text = "</td><td>";
Literal l2 = new Literal();
l2.Text = "</td></tr>";
RadColorPicker CPI = new RadColorPicker();
CPI.PaletteModes = PaletteModes.WebPalette;
CPI.ID = "RadColorPicker" + i;
CPI.ShowIcon = true;
CPI.SelectedColor = System.Drawing.Color.Black;
ImageButton IBVideo = new ImageButton();
IBVideo.ID = "IBVideo" + i;
IBVideo.ImageUrl = "/images/video-icon.jpg";
IBVideo.ToolTip = "Add Video";
IBVideo.Height = 20;
IBVideo.Width = 20;
ImageButton IBAdd = new ImageButton();
IBAdd.ID = "IBAdd" + i;
IBAdd.ImageUrl = "/images/add-icon.png";
IBAdd.ToolTip = "Add Sub-Answers";
//IBAdd.OnClientClick = "showDialog(" + i + ");return false;";
IBAdd.Height = 20;
IBAdd.Width = 20;
//Add Textbox
PanelAnswersToQuestions.Controls.Add(l1);
PanelAnswersToQuestions.Controls.Add(tb);
PanelAnswersToQuestions.Controls.Add(l3);
PanelAnswersToQuestions.Controls.Add(CPI);
PanelAnswersToQuestions.Controls.Add(IBVideo);
PanelAnswersToQuestions.Controls.Add(IBAdd);
PanelAnswersToQuestions.Controls.Add(l2);
}
As you can see I just add controls to the panel, I need to know when that ImageBUtton is hit I can add a Textbox and in this case it could be more then just one textbox to it.
I hope this is clear but for some reason I dont think it is ... sorry.
I have added a radwindow and poping that up sending the Data to the partent via javascript the which created a new problem for me, I can not in javascript seem to find the dynamicly created hiddenfield
function OnClientClose(radWindow) {
var oWnd = $find("<%=RadWindowAddSubAnswer.ClientID%>");
var SubAnswerValues = oWnd.get_contentFrame().contentWindow.document.forms(0).HiddenFieldSubAnswers.value;
alert(SubAnswerValues);
var AnswerID = oWnd.get_contentFrame().contentWindow.document.forms(0).HiddenFieldAnswerID.value;
alert(AnswerID);
var HiddenName = "HiddenFieldSubAnswers" + AnswerID;
alert(HiddenName);
document.getElementById(HiddenName).value = SubAnswerValues;
$get("DivSubAnswers" + AnswerID).innerHTML = SubAnswerValues;
}
The "document.getElementById(HiddenName).value = SubAnswerValues;" seems to never be found, I also tried $get(HiddenName).value = SubAnswerValues; that does not seem to work either both come back as null as for the code behind its:
HiddenField HFSubAnswers = new HiddenField();
HFSubAnswers.ID = "HiddenFieldSubAnswers" + i;
HFSubAnswers.Value = "0";
Im not sure if I got your question right but if you need to dynamically add controls on a Page here is what I can say.
Before adding your control I guess you need to find the control where you need to add it on, Add the control then assign the properties.
PlaceHolder myPlaceHolder = (PlaceHolder)Page.FindControl("PlaceHolder1");
myPlaceHolder.Controls.Add(myButton);
myButton.Text = "Hello World";
For a more detailed expalnation go here http://anyrest.wordpress.com/2010/04/06/dynamically-removing-controls-in-a-parent-page-from-a-child-control/

Controls.remove() method not working in asp.net

I have a web app where the user can create dynamic textboxes at run time. When the user clicks SUBMIT, the form sends data to the database and I want remove the dynamic controls.
The controls are created in the following code:
Table tb = new Table();
tb.ID = "tbl";
for (i = 0; i < myCount; i += 1)
{
TableRow tr = new TableRow();
TextBox txtEmplName = new TextBox();
TextBox txtEmplEmail = new TextBox();
TextBox txtEmplPhone = new TextBox();
TextBox txtEmplPosition = new TextBox();
TextBox txtEmplOfficeID = new TextBox();
txtEmplName.ID = "txtEmplName" + i.ToString();
txtEmplEmail.ID = "txtEmplEmail" + i.ToString();
txtEmplPhone.ID = "txtEmplPhone" + i.ToString();
txtEmplPosition.ID = "txtEmplPosition" + i.ToString();
txtEmplOfficeID.ID = "txtEmplOfficeID" + i.ToString();
tr.Cells.Add(tc);
tb.Rows.Add(tr);
}
Panel1.Controls.Add(tb);
The Remove section of the code is:
Table t = (Table)Page.FindControl("Panel1").FindControl("tbl");
foreach (TableRow tr in t.Rows)
{
for (i = 1; i < myCount; i += 1)
{
string txtEmplName = "txtEmplName" + i;
tr.Controls.Remove(t.FindControl(txtEmplName));
string txtEmplEmail = "txtEmplEmail" + i;
tr.Controls.Remove(t.FindControl(txtEmplEmail));
string txtEmplPhone = "txtEmplPhone" + i;
tr.Controls.Remove(t.FindControl(txtEmplPhone));
string txtEmplPosition = "txtEmplPosition" + i;
tr.Controls.Remove(t.FindControl(txtEmplPosition));
string txtEmplOfficeID = "txtEmplOfficeID" + i;
tr.Controls.Remove(t.FindControl(txtEmplOfficeID));
}
}
However, the textboxes are still visible.
Any ideas?
I would assume that your creating these controls each time the page is loaded or else when your remove code ran on postback it would fail because they would not exist.
So you need to move the create code to NOT happen with every page load by making sure it is wrapped in a if (!IsPostBacK) { ... } statement.
If you do this then you wouldn't need to remove them manually since they are created dynamically and therefore not created by default on each postback.
If you can post where the code that creates the controls is being called from, and the remove as well, I could help you a bit more.
What I ended up doing was instead of deleting the textbox, I deleted the TableRow;

Categories

Resources