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

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.

Related

Interact with non standard control via codebehind

I'm using a CMS plugin with Microsoft Dynamics which features its own controls etc.
I have the following control within a listview, that I need to detect and then potentially update from the CodeBehind file. I know how to do this with a standard control such as a Panel, Div, TextBox etc but dont know how to do it with a control like this.
<crm:Property DataSourceID="Event" PropertyName="Adx_Summary" EditType="html" runat="server"/>
I'm also sure that this is something I NEED to know long term for other similar scenarios.
You can just give it an ID and then work with it like any other control:
<crm:Property DataSourceID="Event" PropertyName="Adx_Summary" EditType="html" runat="server" id="myCustomControl" />
In code:
myCustomControl.WhatEverItSupports();
Of course, this is if this tag is not part of another control and is nested within some sort of template. I can't deduce that from your question

Using a custom control more than once on the same page / form .net

I have been building a custom control for some time now and overcome a number of hurdles. One challenge I have yet to resolve is the ability to use a custom control more than once on the same page.
I have a custom control that functions well on its own, but when two of the same controls are placed on the page the second control is able to control the first one. My guess is that the first one (control) is the first object and the second one is the same object. How can I make sure in the code that if I use the same control more than once on a page it will behave as two separate controls. Are there any specific things I should look at to make sure it allows it to be on a page more than once.
Thanks in advance.
When you add multiple instances of a control, be sure to give them different IDs. Then when writing any code that will interact with them, reference them by that ID.
<%# Register Src="controls/myControl.ascx" TagName="myControl" TagPrefix="uc1" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainPlaceHolder" runat="server">
<uc1:myControl ID="ctlFirst" runat="server">
<uc1:myControl ID="ctlSecond" runat="server">
</asp:Content>
Then in the code behind:
ctlFirst.SomeProperty = true;
ctlSecond.SomeProperty = false;
Place a couple of instances of your custom control onto an ASPX page then view the HTML source and have a look at all the element IDs generated on each of the control instances. ASP.NET will automatically mangle the IDs of your control's children, prefixing them with the ID of the parent control. If you're outputting raw HTML, this might not happen. If there are any duplicate IDs, then that may be the cause of your problem, particularly if you're using client-side logic to manipulate the controls on the page.
Also, make sure that you're not using any session or application variables in your controls.

Can I modify the <head/> section of a Page in .NET from a User Control without runat="server"?

I have a page that does not have runat="server" set in the <head/> section. I do not have access to modify any of the code in the page.
This page contains a user control which I do have access to. Can I add a <meta/> tag to the head section of the page from the user control? It needs to be server-side so a javascript solution won't work.
One option is to create a Response Filter, and then modify the output before it's sent to the user.
https://web.archive.org/web/20211029043851/https://www.4guysfromrolla.com/articles/120308-1.aspx
You can parse the text in
(this.Page.Controls[0] as LiteralControl).Text
to see where the string <head> starts, and insert whatever text you need in there thus injecting your own code into the page header without it being marked with runat="server".
Please be aware though, this is pretty hacky way of getting your code where it most likely shouldn't be (otherwise the <head> element would have been marked as runat="server" so you can access it normally). This will also break if at a later date the head element is changed to be an ASP.NET control. It might will not work with master pages, you will have to walk up the control tree looking for topmost literal element.

ASP.Net: User control with content area, it's clearly possible but I need some details

I have seen two suggestions for my original question about whether it is possible to define a content area inside a user control and there are some helpful suggestions i.e.
Passing in content to ASP.NET user control
and
ASP.NET User Control inner content
Now, I like the theory of the latter better than the former just for aesthetic reasons. It seems to make more sense to me but the example given uses two variables content and templateContent that the answerer has not defined in their example code. Without these details I have found that the example does not work. I guess they are properties of the control? Or some such?
EDIT - DETAILS: What I am trying to do
I have need of an ASP.Net user control that conceals some content in a panel inside a placeholder and asks for the input of a code in a visible panel.
Essentially the user will put their code into the provided textbox in Panel A and submit it, it will be checked and, if it is valid, panel B and the locked content will be displayed.
I have done a test where the content was hard coded into panel B but as soon as I need to make the content a generic input it fails. If it were just text or somesuch then I could make it a property of the control, but as it is, in fact, another User Control I am having some difficulty getting this into the "hidden" panel.
Any other workable solutions are also welcome.
EDIT NOTE: The solution I'm trying to implement this in 2.0 I did find a 3.5 solution which I cannot use.
The former example seems workable but I'd prefer to go with the latter if someone could fill in the blanks for me.
Thanks.
Okay, so this is disturbingly easy but many of the tutorials on the web that talk about this kind of thing push to do extravagant things that require the control to parse ListItems or such.
So this solution is purely so that you can build a control that, for whatever reason, has a placeholder in it that could have anything inside it (kind of like a content area on a Master page). In this instance it happens to be because the Panel containing the placeholder is hidden until appropriate input actions have taken place in another panel.
First, you need to add this:
[ParseChildren(true,"Content")]
[PersistChildren(false)]
just above the part of the control which looks like this:
public partial class MyControl : System.Web.UI.UserControl
then in the control scoped declarations at the head of the control you want to declare thus:
private Control _content;
[PersistenceMode(PersistenceMode.InnerProperty)]
public Control Content { get { return _content; } set { _content = value; } }
Finally you need to place the content into the placeholder like this:
phContent.Controls.Add((Control)_content);
That last line goes into the Page_Init event. For reference "phContent" is the name of the place holder where you want the content to appear, like this:
<asp:Panel ID="pnlLockable" runat="server" Visible="False">
<asp:Placeholder runat="server" ID="phContent" />
</asp:Panel>
On the front end the resulting implementation looks like this:
<uc:MyControl runat="server" ID="lockit1">
<Content>
//...your stuff goes here...
</Content>
<uc:MyControl>
Note that I presume that what is inbetween the Content Tags is a root control. This is because I nested another user control in there. I imagine if you put whatever content you want within a panel or placeholder it should be fine.
Also you can read "How to: Create Templated ASP.NET User Controls". Really helpful.

Setting meta:resourcekey on page load

I have a label on a page which gets localized text through the meta:resourcekey attribute. The issue I have is that I want it to display different text depending on which view of a multiview they're on.
I tried adding the attribute though label.Attributes.Add("meta:resourcekey", "label"), but that doesn't seem to load any text. I tried it on PreRender, and same deal. The attribute appears when I look at the source, but no text is displayed.
Is this possible to do? The other option is to have 2 labels and change the visibility on page load, but that seems like the less elegant solution.
Thanks.
I think what you want for programmatic localisation in code behind is as simple as this:
ctrl.Text = (string)GetLocalResourceObject(“myCtrlKey.Text”);
ctrl.AnotherAttribute = (string)GetLocalResourceObject(“myCtrlKey.AnotherAttribute”);
Using LocalResource means that for a page called MyPage.aspx, you have created a resource file called MyPage.aspx.resx and/or MyPage.aspx.{culturename}.resx in the special directory App_LocalResource.
If you like Global Resources instead of local, use the special directory App_GlobalResource
to hold a resource file called MyResourceFileName.resx and call:
ctrl.Text= (string)GetGlobalResourceObject(“MyResourceFileName”, “myGlobalKey”);
copied from a blog about localization in the code behind
--
PS the reason that Attributes.Add("meta:resourcekey", "label") doesn't work is that "meta:resourcekey" isn't a real attribute and its use in the aspx is not really valid aspx markup - rather it's a preprocessing directive that causes the compiler to turn it into a longer list of attributes name/value pairs, based on what you've put in your resource file.
The approach of trying to assign a meta:resourcekey attribute will not work simply because they are treated specially by the page parser, and replaced before the page lifecycle code even really begins.
But meta:resourcekey is basically a declarative replacement for the code equivalent of accessing local resource files. In other words:
<asp:Label ID="MyLabel" meta:resource-key="MyResourceKey" />
is equivalent to:
<asp:Label ID="MyLabel" Text="<%$ Resources: myResXFile, MyResourceKey %>" />
is equivalent to the code:
MyLabel.Text = Resources.MyResXFile.MyResourceKey;
It looks like you're already dealing with your label in the code if you're trying to assign attributes to it. Why not set it's value in the code?

Categories

Resources