I had looked up the LoadControl(“”) method earlier today, and came upon a short website entry that quickly discussed how to load a web user control (.ascx) dynamically onto a page. The link is:
http://www.codeproject.com/KB/aspnet/LoadingUSerControl.aspx
It mentioned inside that a CMS (content management system) could be built using this method + a database table to track these controls. It got me intrigued, so I decided to pursue it. It’s pretty simple, and actually adds a lot of cool functionality to some of my pages.
I started off by adding this table to my database:
Nothing too fancy here—Just a name, the URL of the control, and then a timestamp column so that one day I can dynamically manage these and use LINQ to SQL to take care of ChangeTracking. Anyway, so the backend is now ready to go.
I have a web.config with all the major web user controls in my project defined, with a name. That way I can just type in something like <MyProgram:MyControl> in my .aspx pages, without having to drag/drop and register them individually. Here’s an example:
<addtagPrefix="KFNet" src="~/UserControls/Blog/ReadBlog.ascx" tagName="ReadBlogEntry"/>
So what if I wanted to load this user control dynamically on a page? Or even one day enable a user to add it to a portal style page? I wrote an entry in my database to match up pretty much exactly what this XML entry looks like. I made its name “ReadBlogEntry” and its url “~/UserControls/Blog/ReadBlog.ascx”
I wrote a custom method in a partial class of my LINQ to SQL object, and it looks like this:
public static string ReturnURLByName(string Name)
{
KfNetUserControl webControl = new KfNetUserControl();
webControl = webControl.SelectCached().FirstOrDefault(m => m.Name == Name);
if (webControl != null)
{
return webControl.URL;
}
else
{
throw new RecordNotFoundException(
string.Format("Failed to find the URL of the user control based off the name, {0}. Please check the method call.",Name));
}
}
You can write this method anyway you’d like, but basically it will select the item from the cached list of user control entries, and return the URL of it. I can then just call this method whenever I want to load a control, and all I need is its name as specified in the web.config / database record. I made it throw an exception if the entry was not found, so that if I mistype a name, I know immediately why a control isn’t loading properly.
Now comes the cool part. I have a webpage that I want to be able to dynamically load web user controls when the user clicks a button. I want the control to appear inside a Modal Pop Up, so that it keeps them in-page. Here is a snippet from the .aspx page code:
<asp:UpdatePanel runat="server" ID="UpdatePanelPage">
<ContentTemplate>
<asp:LinkButton runat="server" ID="EmptyButton" />
<ajaxToolkit:ModalPopupExtender runat="server" ID="GeneralModalPopUp" PopupControlID="ModalPopUpPanel"
TargetControlID="EmptyButton" OkControlID="OkButton" CancelControlID="CancelButton"
EnableViewState="false" BackgroundCssClass="modalBackground" />
<asp:Panel runat="server" ID="ModalPopUpPanel" CssClass="LargeModalPopUp" Style="display: none;
vertical-align: middle;">
<asp:UpdatePanel runat="server" ID="UpdatePanelModalPopUp">
<ContentTemplate>
<asp:PlaceHolder runat="server" ID="DynamicPlaceHolder" />
</ContentTemplate>
</asp:UpdatePanel>
<asp:Button runat="server" ID="OkButton" Text="Ok" />
<asp:Button runat="server" ID="CancelButton" Text="Close" />
</asp:Panel>
Nothing too unusual going on in here. I have a page that’s in an UpdatePanel (for my own reasons) and then a ModalPopUpExtender and its required controls (Panel, Ok/cancel button,etc.) The key thing here is to place an UpdatePanel inside the Modal pop-up Panel, because you will be adding the web user control dynamically. I added a placeholder inside because if I eventually want to add more controls to this UpdatePanel, I need to control exactly where my user control will be added. The placeholder acts as….a placeholder, for my control.
You might also notice I have a LinkButton with an ID of “EmptyButton” and no text value set. I do this because if I set the target control ID to the actual button that the user clicks, it will not post-back properly (since it just executes client-side javascript.) There might be some more elegant way of doing this, but this works for me..
This Modal Pop-Up will act as a general modal pop-up, because I can add any control I want to inside of it. So lets say on the page I have several buttons that the user can click. Depending on the button, the custom control will change. The easiest way I found to do this is using CommandName and CommandArgument. Here’s a button snippet:
<asp:LinkButton ID="ReadBlogPopUpButton" runat="server" Text="[Click To Open]" ToolTip="Show a Quick View of this Item"
CommandName="PopUpModal" CommandArgument="ReadBlogEntry" OnCommand="PopUpControl_Command" style="color: #FF6633;" />
You will notice it references OnCommand=”PopUpControl_Command” which is a custom method I wrote. Here is the code for it, in my .aspx.cs file:
protected void PopUpControl_Command(object sender, CommandEventArgs e)
{
if (e.CommandName == "PopUpModal")
{
Control myDynamicControl = LoadControl(KfNetUserControl.ReturnURLByName(e.CommandArgument.ToString()));
DynamicPlaceHolder.Controls.Add(myDynamicControl);
GeneralModalPopUp.Show();
}
}
So this catch-all command operation will first check to make sure the CommandName is set properly to “PopUpModal” and then it will call my ReturnURLByName method using the CommandArgument.ToString(). I call the .Show() method of the Pop-Up at the end, because if I didn’t ,it wouldn’t show up. This is because of our EmptyButton being the targetID of the extender, and not any other button.
I can now drop in any number of buttons, and all I have to do to make them dynamically generate controls is set their CommandName and CommandArgument, and wire them up to my OnCommand method. No if/else if statements, etc. Very simple!
Cheers,
Samer Paul
Print | posted on Tuesday, September 08, 2009 12:39 PM