Creating aspx textbox from codebehind - c#

how can I create aspx textbox from code behind in C# and how to access its value in code behind ? I do as follows but on every post backs text box is getting cleared. I need to keep its values on post backs.
TextBox txt = new TextBox();
txt.ID = "strtxtbox";
txt.CssClass = "CSS1";
StringBuilder sb = new StringBuilder();
StringWriter writer = new StringWriter(sb);
HtmlTextWriter htmlWriter = new HtmlTextWriter(writer);
txt.RenderControl(htmlWriter);
//lbl is an aspx label
lbl.text += #"<td style='width: 5%;'>" + sb.ToString() + "</td>";
And I access text box value as follows
string tb = Request.Form["strtxtbox"].ToString();

You can start by creating the TextBox control. It must be done in the Init() (Page_Init()) or PreInit() (Page_PreInit()) method, and you have to do it regardless of Page.IsPostBack. This will put the element on the page before the ViewState is loaded, and will allow you to retrieve the value on postback.
var textBox = new TextBox();
Then you should set a few properties on it, including an ID so you can find it later:
textBox.ID = "uxTxtSomeName";
textBox.MaxLength = 10; // maximum input length
textBox.Columns = 20; // character width of the textbox
etc...
Then you need to add it to an appropriate container on the page (Page, or whichever control you want it to appear within):
parentControl.Controls.Add(textBox);
Then on post back, you can retrieve the value, probably in the Load() method (Page_Load()) using the parent's FindControl() function:
var input = (parentControl.FindControl("uxTxtSomeName") as TextBox).Text;
Note: The built-in FindControl() only iterates through immediate children. If you want to search through the entire tree of nested server controls, you may need to implement your own recursive FindControl() function. There are a million and one examples of recursive FindControl() functions on [so] though, so I'll leave that up to you.

The problem is that the control won't be available on postback unless you recreate it every time, which is problematic.
One solution I've used in the past is the DynamicControlsPlaceholder, you can check it out here.

Check this out, it gives you complete example for adding controls at runtime
http://www.codeproject.com/Articles/8114/Dynamically-Created-Controls-in-ASP-NET
http://geekswithblogs.net/dotNETvinz/archive/2009/03/17/dynamically-adding-textbox-control-to-aspnet-table.aspx

Create the textbox as per the code in the comment
TextBox myTextBox=new TextBox();
however, you must set an ID/Name. Additionally, you must create the text box on every postback, in the pre-render or before, so that the value will be populated. If you delay creation of the textbox to later in the page lifecycle, the value will not be populated from the postback, and then you would have to retrieve it from the Request.Response[] collection manually.

Related

add DIV around every asp:DropDownList control code behind

I try to simply add a div wrapper around every control of type <asp:DropDownList> at a global level (if possible). At this point I have solved it with a asp skin adding "default-select" class to all <asp:DropDownList> and then jquery just adding a div for each of them.
$j(".default-select").wrap("<div class='myClass'></div>");
Now, my question. Is it possible to add this div wrapper from the code-behind instead of relying on a javascript.
Control Adapter:
I know this should be possible by writing a control adapter that override <asp:DropDownList> render method (as described here: Dropdownlist control with <optgroup>s for asp.net (webforms)?). However, I just want to add a wrapping div, not rewrite the entire rendering of the <asp:DropDownList> control (which I have to do if i override the method?). Any suggestions? Maybe there is a way to just add something to the existing adapter??
Custom User Control: Another solution would be to build a custom <mycustom:DropDownList> with the wrapping, but, this would force me to replace every instance of <asp:DropDownList> trough the whole project (large project). I rather just change the original control some how so that my styling applies everywhere.
So summary: Is there an easy way to just make all <asp:DropDownList> render as:
<div class="myClass">
<select><option...></select>
</div>
instead of just:
<select><option...></select>
My first attempt (on Page load): I tried to add this code in the Page_load method but I don't find any way to render that div out?
var j = 0;
foreach (DropDownList control in Page.Controls.OfType<DropDownList>())
{
HtmlGenericControl div = new HtmlGenericControl();
div.ID = "div" +j;
div.TagName = "div";
div.Attributes["class"] = "myClass";
div.Controls.Add(control); // or control.Controls.Add(div); but this wouldn't wrap it.
j++;
}
Your solution just about works. Server control can only exist within the scope of a server form, you will need to perform a recursive search on the page or look directly in the form controls collection. Once you have the DropDownList and wrapped it around a div container it will need to be added to the controls collection.
Also, I think it better to perform this in OnPreInit.
protected override void OnPreInit(EventArgs e)
{
base.OnPreInit(e);
var j = 0;
foreach (DropDownList control in form1.Controls.OfType<DropDownList>().ToList())
{
var div = new HtmlGenericControl();
div.ID = "div" + j;
div.TagName = "div";
div.Attributes["class"] = "myClass";
div.Controls.Add(control); // or control.Controls.Add(div); but this wouldn't wrap it.
j++;
form1.Controls.Add(div);
}
}
I hope this is helpful. Let me know how you get on.
Either way what you're wanting is custom and you have to code for it. So IMO, the best and simplest option is the custom control. You may have to spend some time refactoring references to replace your <asp:DropDownList>, but in all the time you've spent trying another way, you could've been done by now. :)
I've learned the hard way that keeping it simple is usually the best way to go.

Is it possible to dynamically add embedded code blocks to asp.net page similar to how controls are added dynamically from code?

One can dynamically add controls to an asp.net page.
Label myLabel = new Label();
myLabel.Text = "Sample Label";
Panel1.Controls.Add(myLabel);
I want to know if it is possible to add embedded code blocks dynamically?
If I do something like the code below, the embedded code will be rendered literally.
// Use <%#Page.Title%> or <%=Page.Title%> for example
LiteralControl literal = new LiteralControl("<%=Page.Title%>");
Panel1.Controls.Add(literal);
The output of the above code will be
<%=Page.Title%>
Is there a way to make ASP.NET evaluate the embedded code blocks that are added dynamically?
LiteralControl literalContols = new LiteralControl();
literalContols.Text = Page.Title;
this.MasterForm.Controls.Add(literalContols);

User Controls required an ID in postback?

I add some div into a panel on server side, when the page is generated, and I add a ID for each one :
HtmlGenericControl divContainerInside = new HtmlGenericControl("div");
divContainerInside.ID = "inside_" + m_oIDCategoria + "_" + numero;
than, on postback (after re-creating them), I cycle them :
foreach (HtmlGenericControl divInside in myPanel.Controls.OfType<HtmlGenericControl>())
{
Response.Write(divInside.ID);
}
all is ok! But, if I remove that divContainerInside.ID when I generate it, I get a NullException cycling them. Why?
I guess you get NullException when you try to read the ID, which you haven't set.
If you change your code like this, you'll get the value:
foreach (HtmlGenericControl divInside in myPanel.Controls.OfType<HtmlGenericControl>())
{
Response.Write(divInside.ClientID);
}
PS: I don't know if you have got this line of code:
myPanel.Controls.Add(divContainerInside);
If you want to find out more about web controls you can read this article and this.
You cant add a control to the page using response.Write you need to add it to the Pages or another controls control collection like below:
Page.Controls.Add(divInside);

asp.net textbox dynamic creation with .CssClass attribute

I am having a scenario by which I have to dynamically create the form based on the user selection. In the form, there are few textboxes which should be added at the end to the Total Textbox.
The way I am distinguishing the textboxes to be added at the end is by specifying as below..
TextBox txt1 = new TextBox();
txt1.ID = "txt1";
txt1.CssClass = "addToTotal";
TextBox txt2 = new TextBox();
txt2.ID = "txt2";
txt2.CssClass = "addToTotal";
TextBox txt3 = new TextBox();
txt3.ID = "txt3";
txt3.CssClass = "txtTotalPoints";
PlaceHolder1.Controls.Add(txt1);
PlaceHolder1.Controls.Add(txt2);
PlaceHolder1.Controls.Add(txt3);
In reality, there is no css class named 'addToTotal' in the site css file. It's just used as a flag to notify me for adding at the end.
Is it a good practice to add a .CssClass even though the actual class does not exist. Are there any pitfalls in using this methodology?
I would assume that the overhead of using a CSS class which does not exist as a marker is minimal, so I wouldn't change your implementation based on that. If you're concerned about best practices - which you could rightly be, CSS classes were never intended to be used like this - you could add a data-* attribute to the input and use that instead:
txt2.Attributes["data-addToTotal"] = "true";
...then finding those elements with JQuery:
$("input[data-addToTotal='true']")
data-* attributes are part of HTML5, but are fully backwards compatible.

Sql Reporting services - find item in report - on load

SQL reporting services has a little search box in the top of the report viewer. When used, it finds the search text, navigates to containing page and highlights the text on the page. My question is how can I do this when the report loads.
Currently I have a reportviewer embedded in my page. Is there a method that will find? I am using sql 2008 express and Dot Net 2
For example I send the serial number 1234 to the report so that when it opens it acts like the user searched for the text and finds it for them in the report.
Ed gave me the answer to the url part. http://server/Reportserver?/SampleReports/Product Catalog&rc:FindString=mystring but I still can't figure out the reportviewer.
Here is some of the page code:
using Microsoft.Reporting.WebForms;
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
Int32 iID = Convert.ToInt32(Request.QueryString["ID"]);
String reportsPath = ConfigurationManager.AppSettings["ReportsPath"];
String sReportName = "ReportInvoice";
reportViewer1.Reset();
reportViewer1.ProcessingMode = ProcessingMode.Remote;
reportViewer1.ShowParameterPrompts = false;
reportViewer1.ServerReport.ReportServerUrl = new Uri(ConfigurationManager.AppSettings["ReportViewerUrl"]);
reportViewer1.ServerReport.ReportServerCredentials = new ReportServerCredentials();//http://localhost/reportserver
reportViewer1.AsyncRendering = false;
ReportParameter[] reportParams = new ReportParameter[1];
reportViewer1.ServerReport.ReportPath = reportsPath + sReportName;
reportParams[0] = new ReportParameter("invoiceID", iID.ToString());
reportViewer1.ServerReport.Refresh();
}
}
Thanks in advance.
See this MSDN page (SQL 2005 version, but 2008 is the same, I believe).
I read through alot of the MSDN articles on the web based report viewer and tried several ways to fire off the search but only found this one to work:
First, in code you can set the search text box like so:
TextBox txt;
txt = (TextBox) this.ReportViewer1.Controls[1].Controls[4].Controls[0];
txt.Text = "test";
I did it in the ReportViewer's PreRender event. Position 1 in the first control list is the toolbar control, #4 is the search group control and then in that group the first control is the text box. The second number (4) could vary based on what you are showing / not showing in the toolbar. I was working with the default report viewer settings. It's a hack but it works.
Then I tried firing off the search event myself but this didn't result in the search working although it did fire off the event and with the correct information....
So here's what I did.
I created a javascript function:
<script type="text/javascript">
function OnFirstLoad() {
if (!isPostBack)
document.getElementById('ReportViewer1').ClientController.ActionHandler('Search', document.getElementById('ReportViewer1_ctl01_ctl04_ctl00').value);
}
</script>
I read the source of the .aspx page and found the text "find" and figured out what the client side call was. You will notice the ctl01 & ctl04 and ctl00 follow the same numbering as the server side code. You would need to change this to reflect your code. Again the second one (ctl04) is the one that is likely to change depending on how your toolbar is setup.
I then set the onload event for the body of the page to the javascript function:
<body onload="OnFirstLoad();">
The last trick was to only call this code the first time. So I added this to the page load event of the form code behind:
If (!IsPostBack)
ClientScript.RegisterClientScriptBlock(GetType(), "IsPostBack", "var isPostBack = false;", true);
else
ClientScript.RegisterClientScriptBlock(GetType(), "IsPostBack", "var isPostBack = true;", true);
This creates a variable that the javascript function checks. On the first go round it's false so it calls the report viewers search function, otherwise it's true and doesn't fire.
This is a pretty bad hack in my opinion and fragile. Changes of the report viewer's toolbar settings may require changes to the javascript and the code to set the text box.
I created a report that had several pages and the first hit wasn't until the third page and it went straight to it. From there the next button worked great until the end of the report.
To bad it's not as simple as the windows based report viewer or the server based report viewer. :)
Good Luck!
If you're trying to do this in a form in code behind then you need to find the report viewer object and add an event to the RenderingComplete that implements Find, so something like this:
public Report()
{
InitializeComponent();
rpViewer.RenderingComplete += new RenderingCompleteEventHandler(rpViewer_RenderingComplete);
}
void rpViewer_RenderingComplete(object sender, RenderingCompleteEventArgs e)
{
int x = rpViewer.Find("0", 1);
}
EDIT:
So, since this in a webpage you can't use the WinForms Controls, however, I was able to wire up a little less hacked version using Javascript that klabranche had used.
Here's a code behind class that adds a javascript function to the body of the html to search the report for the search text that you want:
private void SearchReport(ReportViewer rv, string SearchText)
{
TextBox txt = (TextBox)rv.Controls[1].Controls[4].Controls[0];
txt.Text = SearchText;
this.Body.Attributes.Add("onload", "javascript:document.getElementById('" + rv.ClientID +
"').ClientController.ActionHandler('Search', '" + SearchText + "');");
}
If you don't add the search text to the text box, then it won't show the search string in the text box on the report. This also only works for one report, so if you had additional reports you'd need to alter this. Also, for this to work you need to alter the body tag of your html:
<body id="Body" runat="server">
Have a textbox in your report that uses an expression for its background, set something like:
=iif(me.value = Parameters!Highlight.value, "Yellow", "White")
And of course, make a parameter called Highlight. ;)
Rob

Categories