ASP.NET Web Form User Controls – How to use them

Web Form User Controls are special ASP.NET controls that enables you to dynamically load and add reusable content to your page. Most developers are probably use them in the same way you can add any ASP.NET server control to your page, that is create the Web Form User Control .ascx file, add a reference directive to the Page they want to use it and then simply add it. In this post however we are going to see how extensible a User Control can be. More specifically, we are going to see how easy is to load a User Control template, configure it, that is change any of its properties you want and finally added to a Page. User Controls can be added programmatically to a Page using PlaceHolder controls. Take a look at what we are going to create using User Controls:
actors-list
Let’s start. Create an Empty Web Application Project in Visual Studio and add a new Web Form page named Default.aspx. For the purpose of our example we are going to use the bootstrap library. You don’t need to have any specific knowledge to follow with the example. Add the following code to the Default.aspx page.

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="UserControl.Default" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <link href="content/css/bootstrap.min.css" rel="stylesheet" />
    <link href="content/css/default.css" rel="stylesheet" />
</head>
<body>
    <form id="form1" runat="server">
        <div class="container">
            <div id="myCarousel" class="carousel slide" data-ride="carousel">

                <div class="carousel-inner">               
                    <asp:PlaceHolder ID="PlaceHolderActors" runat="server"></asp:PlaceHolder>
                </div>

                <ul class="nav nav-pills nav-justified">
                    <asp:PlaceHolder ID="PlaceHolderPages" runat="server"></asp:PlaceHolder>
                </ul>


            </div>
            <!-- End Carousel -->
        </div>
    </form>
     <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js" type="text/javascript"></script>
    <script src="content/js/bootstrap.min.js"></script>
    <script src="content/js/default.js"></script>
</body>
</html>

Don’t worry about the stylesheets and javascript files, you will find them all attached in the solution project you can download at the bottom of this page. The most important part at the moment is to note the 2 PlaceHolder controls that are going to host all of our re-usable content we will add later. Let’s start with the first one, the PlaceHolderActors. For our list to work (check GIF image above) we want two specific templates: One for the Active Actor and another for all non-active actors. Add a new folder named “controls” in the application and create a new Web Form User Control named ActiveActor.ascx. Paste the following code to it.

<%@ Control ClassName="ActiveActor" Language="C#" AutoEventWireup="true" CodeBehind="ActiveActor.ascx.cs" Inherits="UserControl.controls.ActiveActor" %>

<div class="item active">
    <asp:Image ID="imgActor" runat="server" />
</div>

Well.. this is pretty much all you need. Make sure you add the attribute “ClassName” cause you will not be able to load this User Control without it. Add a new User Control named “NextActor” and paste the following code.

<%@ Control ClassName="NextActor" Language="C#" AutoEventWireup="true" CodeBehind="NextActor.ascx.cs" Inherits="UserControl.controls.NextActor" %>

<div class="item">
    <asp:Image ID="imgActor" runat="server" />
</div>

The only differences between the two user controls are the ClassName, CodeBehind file name and the div class (active or not). In both of the two User Controls you added, change to the Code view and add the following method.

public void SetImageUrl(string url)
        {
            this.imgActor.ImageUrl = url;
        }

This way you will be able to set the user control’s image control Url. In the same way, add a new User Control named PageTemplate.ascx which is going to hold the li elements required to navigate through our actor elements. These elements are going to be added in the PlaceHolderPages control, inside the ul list. Here is it’s code.

<%@ Control ClassName="PageTemplate" Language="C#" AutoEventWireup="true" CodeBehind="PageTemplate.ascx.cs" Inherits="UserControl.controls.PageTemplate" %>

<li data-target="#myCarousel" runat="server" id="liPage"><a href="#"><small id="actorName" runat="server"></small></a></li>

For this list to work we need to set 2 things before actually add it to the placeholder. The actor’s name of course to navigate to, and a referece to it so that it can slide to the right actor. Change to the code behind file and add the following to methods.

public partial class PageTemplate : System.Web.UI.UserControl
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        public void SetPageNumber(string page)
        {
            this.liPage.Attributes.Add("data-slide-to", page);
        }

        public void SetActorName(string name)
        {
            this.actorName.InnerText = name;
        }
    }

We are done with structuring our code, now let’s see how to use the User Controls. Change to the Default’s code behind file and add the following two lines in the Load event.

protected void Page_Load(object sender, EventArgs e)
        {
            List<string> ActorFileUrls = GetActorFiles();
            BuildPageWithUserControls(ActorFileUrls);
        }

The GetActorFiles function will load all the image file names for each actor we want to display. Don’t worry about the image files, you will find them attached as well. Each image’s file contains the actor’s name we want to diplay.

private List<string> GetActorFiles()
        {
            List<string> files = new List<string>();
            string[] fileNames;
            string baseDirectory = MapPath("~/");
            fileNames = Directory.GetFiles(Path.Combine(baseDirectory, "content", "images"));
            foreach(string file in fileNames)
            {
                files.Add("~/content/images/" + Path.GetFileName(file));
            }
            return files;
        }

actors-file-names
Now the most important part: The function that will take the actor file names list and create the re-usable user controls.

private void BuildPageWithUserControls(List<string> fileUrls)
        {
            int numberOfActorsAdded = 0;

            // Set Active Actor
            string firstActorFile = fileUrls.First();
            ActiveActor activeActor = (ActiveActor)LoadControl("~/controls/ActiveActor.ascx");
            activeActor.SetImageUrl(firstActorFile);
            // Add actor to Actors PlaceHolder
            this.PlaceHolderActors.Controls.Add(activeActor);
            // Create a Page for this Actor
            PageTemplate firstActorsPage = (PageTemplate)LoadControl("~/controls/PageTemplate.ascx");
            firstActorsPage.SetActorName(Path.GetFileNameWithoutExtension(firstActorFile));
            firstActorsPage.SetPageNumber(numberOfActorsAdded.ToString());
            // Add it to Page PlaceHolder
            this.PlaceHolderPages.Controls.Add(firstActorsPage);
            numberOfActorsAdded++;
            fileUrls.Remove(firstActorFile);

            // Continue with other actors
            foreach (string actorFile in fileUrls)
            {
                NextActor nextActor = (NextActor)LoadControl("~/controls/NextActor.ascx");
                nextActor.SetImageUrl(actorFile);
                this.PlaceHolderActors.Controls.Add(nextActor);
                // Create a Page for this Actor
                PageTemplate nextActorsPage = (PageTemplate)LoadControl("~/controls/PageTemplate.ascx");
                nextActorsPage.SetActorName(Path.GetFileNameWithoutExtension(actorFile));
                nextActorsPage.SetPageNumber(numberOfActorsAdded.ToString());
                // Add it to Page PlaceHolder
                this.PlaceHolderPages.Controls.Add(nextActorsPage);
                numberOfActorsAdded++;
            }
        }

Let’s explain the highlighted lines only, cause the following ones are doing the same thing for all other actors. We used the TemplateControl.LoadControl function to load a Web Form User Control by it’s class. We need to cast the returned Control to our User’s Control one. LoadControl takes as a parameter the .ascx file path. After we have load the User Control we can set any of it’s server side properties using the methods we have added before. In this way we can set the specific image we want for each actor.

firstActorsPage.SetActorName(Path.GetFileNameWithoutExtension(firstActorFile));

We started with the first actor cause this will be the active one when the page loads. For all other actors we will uses the NextActor template in the same way. After we set the template’s properties we add it in the respective PlaceHolder.

this.PlaceHolderActors.Controls.Add(activeActor);

We do exactly the same procedure the the PageTemplate User Controls.. Run the application and view the source code in the browser. For each actor template you will see the following code pattern.

<div class="item active">
    <img id="ctl04_imgActor" src="content/images/brad-pitt.jpg" />
</div>

For each page li element the following one.

li id="ctl09_liPage" data-target="#myCarousel" data-slide-to="2"><a href="#"><small id="ctl09_actorName">Emma-Roberts</small></a></li>

That’s it, I hope you have understood how to load and add customized re-usable content to your Page, using the Web Form User Controls. You can download the project with all the required files from here. Keep coding!



Categories: ASP.NET

Tags: ,

1 reply

  1. Great topic, thanks.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: