How to dynamically generate html with .ascx? - c#

I have some settings stored in web.config like this:
<add key="Answers" value="radiobutton1,radiobutton2,radiobutton3"/>
Radiobutton1, radiobutton2 and radiobutton3 are radiobutton label values.
In settings.cs I have a function to retrieve value from web.config:
public static string Answers
{
get
{
return System.Configuration.ConfigurationManager.AppSettings["Answers"];
}
}
.ascx file:
<table runat="server" OnPreRender="Radio_PreRender" id="table1" name="table1">
</table>
My ascx.cs file contains this function:
protected void Radio_PreRender(object sender, EventArgs e)
{
if (Settings.Answers != "")
{
int counter = 0;
string a = Settings.Answers;
string[] words = a.Split(',');
StringWriter stringwriter = new StringWriter();
HtmlTextWriter writer = new HtmlTextWriter(stringwriter);
foreach (string word in words)
{
writer.WriteBeginTag("tr");
writer.WriteBeginTag("td");
writer.Write("abc123");
RadioButton rdb1 = new RadioButton();
rdb1.Checked = true;
rdb1.GroupName = "rdbgroup";
rdb1.ID = "radiobutton" + counter;
rdb1.Text = word;
table1.Controls.Add(rdb1 );
writer.WriteEndTag("td");
writer.WriteBeginTag("tr");
table1.Render(writer);
counter++;
}
}
}
In other words, I want to generate a dynamic number of this code inside table1:
<tr>
<td>
// input type="radiobutton" and label go here.
</td>
</tr>
At the moment radiobuttons are not generated, because they can't be direct child elements to a table. If I specify a div instead, radiobuttons are generated, but everything I try to write with HtmlTextWriter is not. I understand that my html has to be rendered by using table1.Render(writer); or something similar, but I can't figure it out.

You can try creating a table and add it to the page you are working on, using the exmaple below you can replace the textbox with a radiobutton
Here is an example:
//Creat the Table and Add it to the Page
Table table = new Table();
table.ID = "Table1";
Page.Form.Controls.Add(table);
// Now iterate through the table and add your controls
for (int i = 0; i < rowsCount; i++)
{
TableRow row = new TableRow();
for (int j = 0; j < colsCount; j++)
{
TableCell cell = new TableCell();
TextBox tb = new TextBox();
// Set a unique ID for each TextBox added
tb.ID = "TextBoxRow_" + i + "Col_" + j;
// Add the control to the TableCell
cell.Controls.Add(tb);
// Add the TableCell to the TableRow
row.Cells.Add(cell);
}
// Add the TableRow to the Table
table.Rows.Add(row);
}

I do this quite often by running the user control through its full asp.net lifetime and getting it as a string:
http://www.diaryofaninja.com/blog/2009/09/14/a-simple-solution-to-viewing-a-preview-of-any-page-in-your-site
This way you can use ASP.Net as a templating engine for anything
Page tempPage = new Page();
UserControl myUserControl = new MyUserControl();
tempPage.Controls.Add(myUserControl);
StringWriter sw = new StringWriter();
HttpContext.Current.Server.Execute(tempPage, sw, false);
if (!String.IsNullOrEmpty(sw.ToString()))
{
return sw.ToString();
}

Related

Add Dynamic control directly on aspx page not from backend code

I want the checkbox control to be added dynamically with different id's in different th tags generating in a loop
<table border="1">
<thead>
<%string j = " Check"; %>
<%for (int i = 0; i < 10;i++ )
{%>
<th style="padding:2px; width:500px;">Table Head<br /><br />
<%
CheckBox chk = new CheckBox();
chk.ID = i + j;
chk.Text = "I am " + i + j;
%>
//I want this checkbox to be added dynamically here with different id's in different th tags generating in a loop
<asp:CheckBox runat="server" ID="<%=i+j%>"/>
</th>
<%} %>
</thead>
</table>
the way to do this is to create yourself a server-control with all the parameters you need, creating the controls in the OnInit, and rendering html in the RenderControl, and accessing the controls from public props like this:
public class DynamicCbs : Control
{
public int CtrlsCount { get; set; }
public List<CheckBox> lstCheckBoxs;
/// decleration of controls must be in the OnInit since the next stage of the page life cycle is to connect whatever came back from the client to the server
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
lstCheckBoxs = new List<CheckBox>();
for (int i = 0; i < CtrlsCount; i++)
{
string id = "DynamicCbs" + i;
CheckBox cbx = new CheckBox()
{
ID = id,
Text = "i am " + id
};
lstCheckBoxs.Add(cbx);
//add controls to control tree
this.Controls.Add(cbx);
}
}
/// here you must build ur html
public override void RenderControl(HtmlTextWriter writer)
{
writer.RenderBeginTag(HtmlTextWriterTag.Table);
writer.RenderBeginTag(HtmlTextWriterTag.Thead);
foreach (var cbx in lstCheckBoxs)
{
writer.RenderBeginTag(HtmlTextWriterTag.Th);
cbx.RenderControl(writer);
writer.RenderEndTag();
}
writer.RenderEndTag();//thead
writer.RenderEndTag();//table
}
}
full example
ok I found the solution. I have use asp:Table control to solve this problem
My aspx page code is :
<asp:Table ID="ObjectwiseTable2" runat="server"
CssClass="AccessTable" BorderColor="Black" width="100%">
</asp:Table>
My .cs page code to Add content and dynamic content in the table is :
TableHeaderRow thead = new TableHeaderRow();
TableHeaderCell th = new TableHeaderCell();
th.Controls.Add(new LiteralControl("Object Wise Detail(s)"));
th.RowSpan = 2;
thead.Cells.Add(th);
int totalUsers = accesswiseDt.Rows.Count;
for (int User = 0; User < totalUsers; User++)
{
TableHeaderCell th2 = new TableHeaderCell();
th2.Controls.Add(new LiteralControl(accesswiseDt.Rows[User]["users"].ToString()));
IsReviewPending = view_access.IsWaitingForViewAccess(ApplicationTree.SelectedNode.Value, Session["empCode"].ToString(), accesswiseDt.Rows[User]["empcode"].ToString());
if (IsReviewPending)
{
th2.Controls.Add(new LiteralControl("<br />"));
CanReviewAccess = true;
//Code for Adding Dynamic control in specific cell of the table
CheckBox chk = new CheckBox();
chk.ID = ApplicationTree.SelectedNode.Value + "_" + accesswiseDt.Rows[User]["empcode"].ToString();
chk.Text = "Access Reviewed";
th2.Controls.Add(chk);
}
thead.Cells.Add(th2);
}

How to add CheckBox, Label and DDL to ASP.NET page programmatically?

I am trying to add a check box, label and DDL to ASP.NET page (aspx) from my back class in C#. I have been using LiteralControl _liText = new LiteralControl(); to attach label so that I can show them using this.Controls.Add(_liText);in CreateChildControls() method.
How do I add DDL and check box to ASp.NET page from C# code so that my label is in the same line with DDL and checkbox?
I have already made DDL using this syntax:
List<DropDownList> _ddlCollection=new List<DropDownList>();
for (int i = 0; i < 5; i++)
{
_ddlCollection.Add(new DropDownList());
}
Problem is not in this.Controls.Add() which I call from CreateChildControls(). It is OnPreRender() method where I fill ddl and check box. Is LiteralControl class good for this? Here is what I have tried in OnPReRender():
foreach (SPList list in web.Lists)
{
if (!list.Hidden)
{
_liText.Text += #<input type="checkbox">;
_liText.Text += list.Title + "<br />";
}
}
Your controls exist but the page or user control are not aware of them.
You need to add your control to the page
Page.Controls.Add(_ddlCollection);
You can also add your controls to other controls on the page, for example a panel.
panel1.Controls.Add(_ddlCollection);
You are adding a list of dropdowns which I don't think is what you want.
You need to add ListItems instead.
var dropDown = new DropDownList {Id = "dropDown1"};
dropDown.Items.Add(new ListItem("text", "value");
Page.Controls.Add(dropDown);
Add a label for the dropdown.
Page.Controls.Add(new Label {AssociatedControlId = dropDown.Id, Text = "Drop me down"});
For your other controls follow the same process:
Add a checkbox
Don't add an html control to a literal unless that is really what you want.
If you want to be able to access that checkbox in the code behind then you need to add it as an asp.net control. User a placeholder.
placeHolder1.Controls.Add(new CheckBox {Id = "chkBox", Text="Tick me"});
The text property on the checkbox will be the label for the check box and tick/untick the check box when you click on the text.
Output should be
<label for="dropDown1" >Drop me down</label>
<select id="dropDown1" >
<option value="value" >text</option>
</select>
<input type="checkbox" id="chkbox" />
<label for="chkbox" >Tick me</label>
First, you should add a placeholder.
<form id="form1" runat="server">
<asp:PlaceHolder runat="server" ID="phMain"></asp:PlaceHolder>
</form>
Next, if you have add in one line you use table (It is a simple but not recommended method, next step add all to Page and set css style for the page).
protected override void CreateChildControls()
{
base.CreateChildControls();
Table table = new Table();
for (int i = 0; i < 3; i++)
{
TableRow tr = new TableRow();
TableCell tc1 = new TableCell();
tc1.Controls.Add(new LiteralControl(String.Format("Line {0}",i)));
tr.Cells.Add(tc1);
TableCell tc2 = new TableCell();
CheckBox chb = new CheckBox();
chb.ID = String.Format("CheckBox_{0}", i);
chb.Text = String.Format("CheckBox {0}", i);
chb.CheckedChanged += chb_CheckedChanged;
chb.AutoPostBack = true;
tc2.Controls.Add(chb);
tr.Cells.Add(tc2);
TableCell tc3 = new TableCell();
DropDownList ddl = new DropDownList();
ddl.ID = String.Format("DropDownList_{0}", i);
ddl.Items.Add("1111");
ddl.Items.Add("2222");
ddl.Items.Add("3333");
ddl.SelectedIndex = i;
ddl.Enabled = false;
tc3.Controls.Add(ddl);
tr.Cells.Add(tc3);
table.Rows.Add(tr);
}
phMain.Controls.Add(table);
}
void chb_CheckedChanged(object sender, EventArgs e)
{
CheckBox chb = sender as CheckBox;
string ddlid = chb.ID.Replace("CheckBox", "DropDownList");
DropDownList ddl = this.Page.FindControl(ddlid) as DropDownList;
if (ddl != null)
{
ddl.Enabled = chb.Checked;
}
}

get dynamically generated ajax textbox id

I have created a web application in which I need to generate textboxes depending upon the number the user enters.I have used Ajax and created textboxes dynamically but these textboxes are not accessible from code-behind.I have used find control but to no use.This is the code I use to generate textbox.
if (txtnobranches.Text != "")
{
if (Convert.ToInt32(txtnobranches.Text) != 0)
{
div_br.InnerHtml = "<table></table>";
tbl_br.Controls.Clear();
for (int i = 0; i < Convert.ToInt32(txtnobranches.Text); i++)
{
TableRow rowbr = new TableRow();
TableCell cellname = new TableCell();
cellname.Text = "Branch Location " + i.ToString();
rowbr.Cells.Add(cellname);
TableCell cellvalue = new TableCell();
cellvalue.Text = "";
TextBox txt = new TextBox();
txt.Text = "";
txt.ID = "txtbranchloc" + i.ToString();
cellvalue.Controls.Add(txt);
cellvalue.ID = "txtbranchloc" + i.ToString();
rowbr.Cells.Add(cellvalue);
tbl_br.Rows.Add(rowbr);
}
}
}
You can access the element by name using Request.Form["NameOfFormControl"] You will have to make little change in code.
In javascript
txt.Name = "txtbranchloc" + i.ToString();
In Code Behind
Note: Make sure you access it in postback otherwise you get null
if (Page.IsPostBack)
{
string firstTxtVal = Request.Form["txtbranchloc0"].ToString();
string secondTxtVal = Request.Form["txtbranchloc1"].ToString();
}
Using Request.Form Collection

Exported CSV file is empty

I have this code which export data from GridView to csv. It works with other sites but not on this current one I've been developing.
The GridView is binded with DataTable in code behind. Following is the event that binds the fetch and bind the data to GridView.
private void bindGridView()
{
//Fetching data from DB goes here
myTable.Columns.Add("type", typeof(int));
myTable.Columns.Add("rate", typeof(int));
foreach (DataRow rows in myTable.Rows)
{
if (rows["dst"].ToString() == "1875")
{
rows["type"] = 1;
rows["rate"] = 500;
rows.AcceptChanges();
}
else if (rows["dst"].ToString() == "1876")
{
rows["type"] = 0;
rows["rate"] = 30;
rows.AcceptChanges();
}
}
gridViewData.DataSource = myTable;
gridViewData.AllowPaging = true;
gridViewData.PageSize = 10;
gridViewData.DataBind();
}
Following is the button click event to export data from GridView
protected void btnExportCDR_Click(object sender, EventArgs e)
{
if (gridViewData.Rows.Count == 0)
{
lblStatus.Text = "Data is empty. Can not export CDR. Please check your filtering dates.";
}
else
{
Response.Clear();
Response.Buffer = true;
Response.AddHeader("content-disposition", "attachment;filename=CDRMMCC_" + System.DateTime.Now.ToShortDateString() + ".csv");
Response.Charset = "";
Response.ContentType = "application/text";
bindGridView();
gridViewData.AllowPaging = false;
StringBuilder sb = new StringBuilder();
//I did a trace here, gridViewData.Columns.Count is 0. That's why it got skipped, I think.
for (int k = 0; k < gridViewData.Columns.Count; k++)
{
sb.Append(gridViewData.Columns[k].HeaderText + ",");
}
sb.Append("\r\n");
for (int i = 0; i < gridViewData.Rows.Count; i++)
{
for (int k = 0; k < gridViewData.Columns.Count; k++)
{
sb.Append(gridViewData.Rows[i].Cells[k].Text + ",");
}
sb.Append("\r\n");
}
Response.Output.Write(sb.ToString());
Response.Flush();
Response.End();
}
}
Please advice.
If you use the AutoGenerateColumns property of the GridView set to true the Columns collection will be empty. The MSDN documentation for this property says:
"Automatically generated bound column fields are not added to the Columns collection".
This is the reason your Columns collection is empty. As Henk Holterman pointed out use your DataTable directly to generate your CSV file.
An alternative approach would be to set the AutoGenerateColumns property to false and define the Columns explicitly.
In addition to Hans answer, you can use RenderControl of the GridView which reduces your work.
StringWriter strWriter = new StringWriter();
HtmlTextWriter htmlWriter = new HtmlTextWriter(strWriter);
MyGridView.RenderControl(htmlWriter);
Response.Write(strWriter.ToString());

Get div control by name from codebehind

Ok, I want to access div control by id witch is changed dynamically from C# code. Maybe it will be clearer with code:
string divHtml = "";
for (int j = 1; j < 4; j++)
{
string ph = "placeHolder" + j;
Control phd = (Control)FindControl(ph);
StringWriter sw = new StringWriter();
HtmlTextWriter w = new HtmlTextWriter(sw);
phd.RenderControl(w);
divHtml = divHtml + sw.GetStringBuilder().ToString();
}
and ascx part is:
<div runat="server" id="placeHolder1" class="placeholder" >
</div>
It pass compile time but phd is at null value, not to the value of control. It works fine if i access control directly like this:
StringWriter sw = new StringWriter();
HtmlTextWriter w = new HtmlTextWriter(sw);
placeHolder1.RenderControl(w);
divHtml = divHtml + sw.GetStringBuilder().ToString();
Thank you in advance....
FindControl finds only controls in the first level, so if your control is located down in the control tree you need to write your own nested FindControl to make it work.
Have look at ASP.NET Is there a better way to find controls that are within other controls? for more info.
Or if you have the parent (page) it should work to call page.FindControl("placeHolder1") on that control directly.
I figured that it is problem with nesting, thanks to #bang. But since I use master page to display my content, this is solution that is best for me:
for (int j = 1; j < 4; j++)
{
string ph = "placeHolder" + j;
ContentPlaceHolder cph = this.Master.FindControl("MainContent") as ContentPlaceHolder;
Control ctrlPh = cph.FindControl(ph);
StringWriter sw = new StringWriter();
HtmlTextWriter w = new HtmlTextWriter(sw);
ctrlPh.RenderControl(w);
divHtml = divHtml + sw.GetStringBuilder().ToString();
}
Thank you #bang, you pushed me in right direction.

Categories