ASP.NET dynamically generate HTML with server controls - c#

When i need to set some value to a Javacript, or any other part of the code, i usually use this:
<script>
<%# SomeFunction() %>
</script>
And this also works for HTML in the document body, like...
<somehtmltag property="<%# SomeFunction2() %>">
And in the code behind i create the function that returns a string, with all the necessary code.
If i add some parameter to a user control like:
<ts:PeopleCard ID="us" runat="server" Visible="<%# IsVisivle() %>" />
It also works, but i try to create the entire user control it does not work.
<%# AddUserControl() %>
Function AddUserControl() as String
Return "<ts:PeopleCard ID=""us"" runat=""server"" Visible=""true"" />"
End Function
I understand that this does not work, because this code must be processed by the server to be converted in the actual code.
The final HTML, it shows:
<ts:PeopleCard ID="us" runat="server" Visible="true" />
when it shouldn't, it should show the processed HTML\css by the server.
So my question is, is it possible to create a control this way? Is it possible to force ASP.NET to "re-process" the page, after I changed its contents in code behind?
I understand there's several other ways to do it. Including, creating the user control in conde behind.
But i need to know, if is possible to do this way...

Usually you have a parent tag that is runat server and you can then add your own object to it.
Dim newTag as New PeopleCard
newTag.Visible = true
pnl.Controls.Add(newTag)
An other option I've done is the past is to add a RenderMethod to a control. Each control have a SetRenderMethodDelegate function and it allows you to write directly to the HtmlTextWriter. This won't create an object for the controls you create yourself.

Related

Adding ASP.NET User Controls at runtime via <script runat="server">

I am having trouble executing a control inside the <script runat="server"> tags in an *.aspx page.
The control works when it is defined declaratively in the HTML section of the page, but I am unable to make it work when placed within the script tag itself.
At the beginning of the page I register my control with:
<%# Register assembly="App_Web_exemple.ascx.cc671b29" namespace="Moncontrol" tagprefix="moncontrol" %>
Then, in the HTML, I call it (successfully) with the following declaration:
<moncontrol:exemple ISBN="9782894646151" runat="server" />
When I try to add it programmatically within the <script runat="server">, however, I am unable to execute it. I tried with the tags <asp:Text /> and <asp:Literal />, as follows, but that also doesn't doesn’t work.
In the HTML part:
<asp:Text id="TestControl" runat="server" />
In the script part
TestControl.Text = "<moncontrol:exemple ISBN=\"9782894646151\" runat=\"server\" />";
To clarify, what you're looking to do is programmatically add a User Control to your Web Forms page at runtime. There are a few ways of accomplishing this.
Before we begin, it's worth noting that the code you wrote likely "works" insomuch that it compiles and doesn't throw a runtime error. But it's also not executing the control. I suspect if you look at your HTML, you'll find the control declaration being output as a string literal (i.e., unprocessed by the server). It is then disregarded by the browser since it doesn't know what the <moncontrol:exemple /> tag represents. That's obviously not what you want.
Establishing a Control Container
Regardless of which approach you take, you'll want to start with some type of container on your page that you can add the control to, such as a Panel. If you don't want the container to output any wrapper markup, you can use a Placeholder:
<asp:Placeholder id="ControlContainer" runat="server" />
This serves a similar purpose as your current Text control, except its only purpose is to provide a container that you will add your user control to. From ASP.NET's perspective, however, this can be any type of server control, including a <script runat="server">, as per your request. More on that later.
Programmatically Creating the Control
Next, you're going to create the control programmatically. This is where we run into various options. The most universal approach is to use ParseControl() method (reference). This looks something like this:
Control control = Page.ParseControl("<%# Register assembly=\"App_Web_exemple.ascx.cc671b29\" namespace=\"Moncontrol\" tagprefix=\"moncontrol\" %><moncontrol:exemple ISBN=\"9782894646151\" runat=\"server\" />");
That will parse the control using the same method that processes the declarative syntax on the page, and return a Control object with your Exemple control as the first control in its Controls collection.
I find that syntax a bit sloppy, however, since it's representing a .NET object and its properties as a string literal. Given that, there are some cleaner approaches. In this case, it appears that your control is being compiled into an assembly and, therefore, likely has a Code Behind defined which inherits from UserControl. If so, you should be able to simply do something like:
Exemple control = new Exemple();
And then set the properties on it programmatically, the way you would in any other C# object. Much cleaner!
If your control was instead being compiled dynamically by the server, then you'd instead use the Reference directive with the LoadControl() method, as described in the MSDN article How to: Create Instances of ASP.NET User Controls Programmatically. I don't believe that method will work for you, however.
Adding the Control Instance to the Page
Regardless of which approach you take, the next step is the same: you then add the control you've programmatically added to your page by adding it to the Controls collection of the target container. E.g.,:
ControlContainer.Controls.Add(control);
Note: You can technically just add this to the Page class's Control collection, too, but that doesn't give you any control over where on the page it is placed; having a PlaceHolder control (or equivalent) lets you specify exactly where you want the control to appear.
I hope this helps. There are a couple of caveats depending on how you wrote and compiled your control, but this should give you the basic structure needed to address your problem.

Embedded code (<%= %>) in button control

I'm working on a project where I'm using the <%= getString("key")%> to dynamically get the appropriate text.
this works great when i use it in simple p tags, but i can't find a way to do this with controls like Button/Label etc.
Is there any way, other than calling
Mybutton.Text = getstring("key");
to dynamically add the text?
The idea is that getString retrieves af language code, and depending on that code gets a string in the appropiate language.
I've been looking around, but all i come across is using the embedded code tags directly in the aspx pages, which wont cut it for buttontext.
If you can use DataBinding instead of the <%= operator, you can use:
<asp:Button ID="MyButton" Text='<%# getstring("key") %>' />
This is a good explanation of why <%= won't work in this context.

ajaxfileupload multiple inputs on page

I'm using ajaxFileUpload as described here: http://www.asp.net/ajaxLibrary/AjaxControlToolkitSampleSite/AjaxFileUpload/AjaxFileUpload.aspx
It is working fine except when I have multiple file upload controls on the same page. Specifically, I am trying to upload different files for different questions. When I upload the first on the page, it works fine, but the one lower down on the page will only upload it's file into the answer for the first question.
I'm not sure that makes sense... so it may help you to know that my page is populated with questions dynamically using ascx files. The document ascx file looks like this:
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="Document.ascx.cs" Inherits="ScholarshipApplication.controls.questions.Document" %>
<ajaxToolkit:AjaxFileUpload OnUploadComplete="UploadComplete" ID="FileUploadControl" MaximumNumberOfFiles="1" runat="server" AllowedFileTypes="png,jpg,jpeg,pdf,tiff,tif,gif" />
<asp:LinkButton ID="downloadButton" runat="server" CausesValidation="false" OnClick="downloadButton_Click" />
And the code behind:
public void UploadComplete(object sender, AjaxFileUploadEventArgs e)
{
entry.data = e.FileName;
entry.setDocumentData(e.GetContents());
this.downloadButton.Text = e.FileName;
}
My initial thoughts are that somehow I need to help the control's generated javascript to know which question it should be triggering when.
I believe this is a bug in control or this was implemented by some non-obvious reason. Actually, this control doesn't support multiple instances on a page. Consider to use AsyncFileUpload control instead or customize a bit sources of the AjaxFileUpload control. If you prefer second option then you need to download sources from here: http://ajaxcontroltoolkit.codeplex.com/SourceControl/BrowseLatest and change AjaxFileUpload.cs file (here is a path: /Server/AjaxControlToolkit/AjaxFileUpload/AjaxFileUpload.cs). What you need to do is to change ContextKey constant to property for combining context key guid with unique id of control:
public class AjaxFileUpload : ScriptControlBase
{
private const string ContextKeySuffix = "{DA8BEDC8-B952-4d5d-8CC2-59FE922E2923}";
private string ContextKey
{
get { return this.UniqueID + "_" + ContextKeySuffix; }
}
Actually, if you'll look on PreRender method of AjaxFileUpload class you'll easy realize reson for such behavior of this control (the first control handle uploads from all sibling controls on a page).
as per my understanding You need a hidden field variable to identify your question id IN UserControl:
<input type="hidden" id="hdnQuestionId" runat="server"/>
while populating/generating question you need to set this variable , and when you upload the doc , fetch this hidden value and use it.
I created a data attribute named "data-upload-type" on ALL AjaxFileUpload controls and set it to the name of the type. Then I set up the client call to grab that value and set a cookie with the same value. The cookie IS received on the server side functions and I branch based on the value I receive.
Here is an example:
function StartUpload(sender, args) {
var t = $(sender._element).attr('data-upload-type');
document.cookie = 'upload-type=' + $(sender._element).attr('data-upload-type') + ';';
}
<asp:AjaxFileUpload ID="afuUploader1" runat="server" OnClientUploadStart="StartUpload" OnUploadComplete="UploadComplete" OnClientUploadComplete="UploadComplete" data-upload-type="UploadType2"></asp:AjaxFileUpload>
Then in your server side upload call simply check Response.Cookies("upload-type").
Works like a charm!

C# Script output in aspx page

I am having issues with the output of my C# script embedded in my asp.net code. The output is generated after clicking a submit button for a web form. This web form is at the top of the page. The output, when clicking submit, is currently being placed above the web form which is in turn pushing the web form underneath it. I would like the opposite to happen. I want it to output below my web form. The way I generate output from my script is as follows:
Response.Write("<p>");
foreach(obj in arr){
Response.Write(obj);
}
Response.Write("</p>");
Also if it matters, I initialize the script with runat="server". The script gets called when the user selects "submit" near the web form. Thanks in advance. I've been trying to format this thing for quite some time now.
You would be better off putting a 'literal' object in the place on your page precisely where where you want the result to appear, and then, instead of spitting out HTML with response.write, you assign the desired text to the literal in your code-behind.
Like this:
<html>
<p>
<asp:Literal ID="ltlTest" runat="server"></asp:Literal>
</p>
</html>
and then in your code behind:
ltlTest.Text = "the string you want to show...";
You can include html tags in the string assignment, though generally I try not to.
You've got some choices.
You can make arr a public property, and then use <% foreach (var obj in arr) Response.Write(obj); %> directly in the page markup where you want it.
You can put in an <asp:Literal runat="server" ID="Literal1"> control and then set Literal1.Text = ... in your code. This achieves the same, but with ViewState (so the value is persisted on postbacks).
If you'd like the result to be rendered within <span /> tags, you can use an <asp:Label /> control. This is usually the best choice for displaying messages to the user.

ASP.NET Custom non-self-closing control

When building a custom control, how would you access the content between the opening and closing control tags?
<my:tag runat="server">
<p>...markup</p>...
</my:tag>
I am currently successfully using the Render method to output arbitrary markeup, but cannot seem to find out how to access the contained markup.
Take a look at this.Controls. This article :
http://msdn.microsoft.com/en-us/library/system.web.ui.control.controls(VS.71).aspx states "On an ASP.NET page, when controls are added declaratively between the opening and closing tags of a server control, ASP.NET automatically adds the controls to the containing server control's ControlCollection. "
As far as I understand, if you have
<yourcode:yourcontrol id="asdf" runat="server">
<p id="innerP" runat="server">Text here</p>
</yourcode:yourcontrol>
Then it would be possible to call this.FindControl("innerP").text="Other text here, since the P tag is generated on the server side.
However, if you do not have the runat="server" set on the P element:
<yourcode:yourcontrol id="asdf" runat="server">
<p id="innerP">Text here</p>
</yourcode:yourcontrol>
then you only can only find it through this.controls[0] since all the content will be rendered into a single Literal control.
I think you want to do this:
<my:tag runtat="server">
<p><asp:Label id="markupLabel" runat="server"/></p>
</my:tag>
And from the code-behind
markupLabel.text = "Foo";
If you add an ID to the my:tag tag, you should be able to access the controls inside of it using the .Controls collection of the tag.

Categories

Resources