Walkthrough: Creating Reusable Elements with ASP.NET User Controls
ASP.NET user controls let you encapsulate the functionality of multiple server controls in a unit. User controls are made up of one or more ASP.NET server controls—Button controls, TextBox controls, and so on—along with any code that is required for the controls to perform the function that you want to accomplish. The user control can also include custom properties or methods that reveal the functionality of the user control to a container, which is typically an ASP.NET page.
In this walkthrough, you will create an ASP.NET user control that acts as a picker control. The picker control has two lists, with a set of choices in one list (the source). Users can select items in the SourceList list, and then add the items to the TargetList list.
This walkthrough has three parts, as follows:
In the first part, you will create the basic user control, adding controls and code.
In the second part, you will create a new ASP.NET page (the host page), and then add the user control to the ASP.NET page.
In the third part, you will add custom properties and methods to the user control so that you can interact with the control from the host page.
Tasks illustrated in this walkthrough include the following:
Creating a user control and adding ASP.NET server controls to the user control.
Creating properties and a method in the user control.
Adding a user control to a host page.
Adding code to the host page to handle the user control.
Prerequisites
In order to complete this walkthrough, you will need the following:
The Microsoft Visual Web Developer Web development tool.
The Microsoft .NET Framework.
This walkthrough assumes that you have a general understanding of working in Visual Web Developer. For an introduction, see Walkthrough: Creating a Basic Web Page in Visual Studio.
Creating the Web Site
If you have already created a Web site in Visual Web Developer (for example, by completing Walkthrough: Creating a Basic Web Page in Visual Studio), you can use that Web site and go to the next section. Otherwise, create a new Web site and page by following these steps.
This walkthrough uses a Web site project. You could use a Web application project instead. For information about the difference between these Web project types, see Web Application Projects versus Web Site Projects.
To create a file system Web site
Open Visual Web Developer.
On the File menu, point to New, and then click Web Site.
The New Web Site dialog box appears.
Under Visual Studio installed templates, click ASP.NET Web Site.
In the right-most Location box, enter the name of the folder where you want to keep the pages of the Web site.
For example, type the folder name C:\WebSites.
In the Language list, click the programming language that you prefer to work in.
Click OK.
Visual Web Developer creates the folder and a new page named Default.aspx.
Creating the User Control
Creating a user control is similar to creating an ASP.NET Web page. In fact, a user control is effectively a subset of an ASP.NET page and it can include most of the types of elements that you put on an ASP.NET page.
To create a user control
In Solution Explorer, right-click the name of the Web site, and then click Add New Item.
In the Add New Item <Path> dialog box, under Visual Studio installed templates, click Web User Control.
In the Name box, type ListPicker.
The user control file will have an .ascx extension, which is added automatically to ListPicker.
In the Language list, select the programming language that you prefer to work in.
Click Add.
The new control is created and is opened in the designer. The markup for the control looks similar to that for a page, with one important exception: there is no @ Page directive at the top of the page. Instead, there is an @ Control directive, which identifies the file to ASP.NET as a user control.
Adding Server Controls to the User Control
In this part of the walkthrough, you will add the controls that make up the user interface for the user control.
To add server controls
Switch to Design view.(If you are working with a code-behind page, switch to the ListPicker.ascx control and then switch to Design view.)
On the Table menu, click Insert Table.
Use the Insert Table dialog box to create a table with one row and three columns, and then click OK.
You are creating the table to hold the controls; that is, a layout table.
In the table, in the left column, type Available, and then press ENTER to create a new line.
In the right column, type Selected, and then press ENTER to create a new line.
from the Standard group in the Toolbox, drag the following controls onto the table and set their properties as indicated.
Control
Properties
Drag a ListBox to the left column and place it under Available.
Height: 200px
ID: SourceList
Width: 200px
Drag a Button to the middle column.
ID: AddAll
Text: >>
Drag a Button to the middle column.
ID: AddOne
Text: (SPACEBAR)>( SPACEBAR)
Drag a Button to the middle column.
ID: Remove
Text: (SPACEBAR)X(SPACEBAR)
Drag a ListBox to the right column and place it under Selected.
Height: 200px
ID: TargetList
Width: 200px
ImageButton controls can be used instead of Button controls so that an image is displayed that responds to mouse clicks. However, for this walkthrough, it is sufficient to use text that emulates the type of graphic that is frequently used to indicate Add All, Add, and Remove, which are the two right angle brackets (>>), one right angle bracket (>), and the X, respectively.
If you want, adjust the width and height of the table columns to your preference.
Click the SourceList list, and then in Properties, for the Items property, click the ellipsis (…) button.
The ListItem Collection Editor dialog box appears.
Click Add three times to add three items
For the first, second, and third item, under ListItem properties, set Text to A, B, and C, respectively.
You are creating test data for now. Later in this walkthrough, in "Adding Custom Properties and Methods to the User Control," you will remove the test data and add code to load the SourceList list dynamically.
Adding Code to Handle User Selections
Users will select items using the buttons that are in the middle column of the table. Therefore, most of the code for the control is in handlers for the Click events.
To add code to handle user selections
In Design view, double-click the >> (AddAll) button to create an event handler for the Click event, and then add the following highlighted code.
Protected Sub AddAll_Click(ByVal sender As Object, _ ByVal e As EventArgs) Handles AddAll.Click TargetList.SelectedIndex = -1 Dim li As ListItem For Each li In SourceList.Items AddItem(li) Next End Sub
protected void AddAll_Click(object sender, EventArgs e) { TargetList.SelectedIndex = -1; foreach(ListItem li in SourceList.Items) { AddItem(li); } }
The code loops through all the list items in the SourceList list. For each item, it calls the AddItem method and passes it the current item. Later in this procedure, you will write the code for the AddItem method.
Switch to Design view, double-click the > (AddOne) button to create an event handler for the Click event, and then add the following highlighted code:
Protected Sub AddOne_Click(ByVal sender As Object, _ ByVal e As EventArgs) Handles AddOne.Click If SourceList.SelectedIndex >= 0 Then AddItem(SourceList.SelectedItem) End If End Sub
protected void AddOne_Click(object sender, EventArgs e) { if(SourceList.SelectedIndex >= 0) { AddItem(SourceList.SelectedItem); } }
This code first checks that there is a selection in the SourceList list. If there is, the code calls the AddItem method, which you will write later in this procedure, passing it the item that is currently selected in the SourceList list.
Switch to Design view, double-click the X (Remove) button to create an event handler for the Click event, and then add the following highlighted code:
Protected Sub Remove_Click(ByVal sender As Object, _ ByVal e As EventArgs) Handles Remove.Click If TargetList.SelectedIndex >= 0 Then TargetList.Items.RemoveAt(TargetList.SelectedIndex) TargetList.SelectedIndex = -1 End If End Sub
protected void Remove_Click(object sender, EventArgs e) { if (TargetList.SelectedIndex >= 0) { TargetList.Items.RemoveAt(TargetList.SelectedIndex); TargetList.SelectedIndex = -1; } }
The code first checks that the TargetList list contains a selection. If there is a selection, the code removes the selected item from the list and the selection.
Add the following AddItem method:
Protected Sub AddItem(ByVal li As ListItem) TargetList.SelectedIndex = -1 TargetList.Items.Add(li) End Sub
protected void AddItem(ListItem li) { TargetList.SelectedIndex = -1; TargetList.Items.Add(li); }
This code unconditionally adds an item to the TargetList list. Later in this walkthrough, in "Adding Custom Properties and Methods to the User Control," you will improve this code by adding the option to determine whether there are duplicates.
You cannot directly test a user control, because it must be hosted in a page. In the next section, you will create an ASP.NET Web page where you can work with the control.
Using the User Control
Like any control, a user control must be hosted in a page. In this part of the walkthrough, you will create a host page for the control, and then you will add a user control to the page.
To create a host page
In Solution Explorer, right-click the name of the Web site, and then click Add New Item.
Under Visual Studio installed templates, click Web Form.
In the Name box, type HostUserControl.
In the Language list, select the language that you prefer to work in, and then click Add.
The new page appears in the designer.
To add the user control to the page
Switch to Design view.
From Solution Explorer, drag the user control file (ListPicker.ascx) onto the page.
Note Be sure that you are in Design view when you drag ListPicker.ascx onto the page.
The control appears in the designer.
Switch to Source view.
Placing the user control on the page creates two new elements in the page:
At the top of the page is a new @Â Register directive and it looks similar to the following:
<%@Â Register Src="ListPicker.ascx" TagName="ListPicker" TagPrefix="uc1" %>
The @Â Register directive is required, because the user control is an external component. The values that are in the directive provide information that is required by ASP.NET to find the control when compiling and running the page. Together, the TagPrefix and TagName attributes specify how the user control is declared on the page. The Src attribute specifies the file, and if it is necessary, the path, where the source file is located.
The second new element is the element for the user control and it looks similar to the following:
<uc1:ListPicker id="ListPicker1" Runat="server" />
The element for a user control looks similar to the element for an ordinary ASP.NET server control. The difference is that the user control has a different tag prefix (uc1) and a unique tag name (ListPicker). Although the values were established automatically by the @Â Register directive when you placed the user control on the page, you can use any tag prefix and tag name for your user control, as long as the values are not already being used in the page.
Testing the User Control
Now, you can test the preliminary version of the user control.
To test the user control
Press CTRL+F5 to run the page.
The page appears in the browser and you can see the two lists and three buttons that make up your user control.
Click the >> (AddAll) button.
All values from the SourceList list are copied to the TargetList list.
Click each item in the TargetList list in turn, and then click the X (Remove) button until you have removed all items.
Select a single value in the SourceList list, and then click the > (AddOne) button.
The single value is copied to the TargetList list.
Optionally, experiment more with the control until you are sure that it works as you intend it to.
When you are finished, close the browser.
Adding Custom Properties and Methods to the User Control
Your user control now works, but it is not yet useful as a general-purpose control. A more practical version of the user control would let you do the following:
Specify the list of items to display in the SourceList list dynamically.
Get the list of items that the user selected in the TargetList list.
Specify whether you want to allow duplicate values in the TargetList list, optionally.
Provide a way for users to clear all items in the TargetList list quickly.
Performing these tasks requires that the host page can communicate with the user control, both to share values (set and read properties) and to issue commands (call methods). In this part of the walkthrough, you will change the user control and add some members (properties and methods) to it.
You will add two properties to the user control. The first property retrieves the list of items that are in the TargetList list. The second property lets you specify whether the TargetList list accepts duplicate values. Later in this section, you will add a method that will let you populate the SourceList list.
To add code to define custom properties
For the ListPicker control, open or switch to the code file.
Use the following code to create the SelectedItems property:
Public ReadOnly Property SelectedItems() As ListItemCollection Get Return TargetList.Items End Get End Property
public ListItemCollection SelectedItems { get { return TargetList.Items ; } }
The SelectedItems property retrieves the values that are in the TargetList list. It can be read-only, because you will never have to set the values in the TargetList list programmatically.
Use the following code to create the AllowDuplicates property:
Public Property AllowDuplicates() As Boolean Get Return CType(ViewState("allowDuplicates"), Boolean) End Get Set(ByVal value As Boolean) ViewState("allowDuplicates") = value End Set End Property
public Boolean AllowDuplicates { get { return (Boolean)ViewState["allowDuplicates"]; } set { ViewState["allowDuplicates"] = value; } }
The AllowDuplicates property is a read/write property. The value of the AllowDuplicates property must be saved explicitly in View state so that it persists between round trips. (The SelectedItems property does not have to be explicitly saved in View state, because the TargetList list saves the values in View state.)
You now have the properties defined. However, you still must modify the existing code in the user control to take advantage of the AllowDuplicates property setting.
To modify existing code to use the AllowDuplicates property
Find the AddItem method that you wrote in "Adding Code to Handle User Selections," earlier in this walkthrough, and replace the contents with the following highlighted code:
Protected Sub AddItem(ByVal li As ListItem) TargetList.Selectedindex = -1 If Me.AllowDuplicates = True Then TargetList.Items.Add(li) Else If TargetList.Items.FindByText(li.Text) Is Nothing Then TargetList.Items.Add(li) End If End If End Sub
protected void AddItem(ListItem li) { TargetList.SelectedIndex = -1; if (this.AllowDuplicates == true) { TargetList.Items.Add(li); } else { if (TargetList.Items.FindByText(li.Text) == null) { TargetList.Items.Add(li); } } }
The code performs the same function as before (adding an item to the TargetList list), but now the code checks to determine whether the AllowDuplicate property is set to true. If the AllowDuplicate property is set to true, the item is added. If the AllowDuplicate property is set to false, the code looks for an existing item with the same value as the proposed new item, and then adds the new item if no existing item is found.
Because you will be setting the contents of the SourceList list using a property, you can remove the test data that you entered in "Adding Server Controls to the User Control," earlier in this walkthrough.
To remove the test data for the SourceList list
Switch to Design view.
Click the SourceList control, and then, in Properties, for Items, click the ellipsis (…) button.
The ListItem Collection Editor appears.
Click the Remove button to remove each sample item, and then click OK.
Adding a Method to the User Control
You can also add methods to perform tasks in the user control when the methods are called by code in the host page. To illustrate this, in this walkthrough, you will add two methods. The first method can be called to add items to the SourceList list. The second method clears the contents of the TargetList list.
To add a method to clear the TargetList list
Use the following code to add the AddSourceItem method:
Public Sub AddSourceItem(ByVal sourceItem As String) SourceList.Items.Add(sourceItem) End Sub
public void AddSourceItem(String sourceItem) { SourceList.Items.Add(sourceItem); }
Use the following code to add the ClearAll method:
Public Sub ClearAll() SourceList.Items.Clear() TargetList.Items.Clear() End Sub
public void ClearAll() { SourceList.Items.Clear(); TargetList.Items.Clear(); }
On the File menu, click Save All to save the changes that you made to the user control.
Testing the User Control Properties and Method
The final task in this walkthrough is to enhance the host page to be able to share values with the user control. You can set some of the properties for the user control declaratively. (You cannot set the SourceList list directly using the code in this walkthrough, but you can set it programmatically.) In this procedure, you will set the AllowDuplicates property to a default value of true.
To set user control properties declaratively
Switch to or open the HostUserControl.aspx page.
In Source view, set AllowDuplicates declaratively by using syntax that it similar to the following:
<uc1:ListPicker id="ListPicker1" Runat="server" AllowDuplicates="true" />
Notice that you obtain Microsoft IntelliSense functionality for AllowDuplicates.
Working with the User Control Programmatically
You can also work with the user control programmatically, setting and retrieving the properties and calling the methods. To illustrate how to work with the user control programmatically, you will add some controls to the host page.
To work with the user control programmatically
Switch to Design view.
From the Standard group in the Toolbox, drag the following controls onto the table on the host page, and then set the properties as indicated.
Control
Properties
TextBox
ID: NewItem
Text: (empty)
Button
ID: AddItem
Text: Add Item
Button
ID: LoadFiles
Text: File List
Button
ID: ClearSelection
Text: Clear All
CheckBox
AutoPostBack: True
Checked: True
ID: AllowDuplicates
Text: Allow duplicates
Button
ID: ShowSelection
Text: Show Selection
Label
ID: Selection
Text: (empty)
In Design view, double-click AllowDuplicates to create an event handler for the CheckedChanged event, and then add the following highlighted code:
Protected Sub AllowDuplicates_CheckedChanged( _ ByVal sender As Object, _ ByVal e As EventArgs) Handles AllowDuplicates.CheckedChanged ListPicker1.AllowDuplicates = AllowDuplicates.Checked End Sub
protected void AllowDuplicates_CheckedChanged(Object sender, EventArgs e) { ListPicker1.AllowDuplicates = AllowDuplicates.Checked; }
Switch to Design view, double-click AddItem to create an event handler for the Click event, and then add the following highlighted code:
Protected Sub AddItem_Click(ByVal sender As Object, _ ByVal e As EventArgs) Handles AddItem.Click Dim sourceItem As String = Server.HtmlEncode(NewItem.Text) ListPicker1.AddSourceItem(sourceItem) End Sub
protected void AddItem_Click(object sender, EventArgs e) { ListPicker1.AddSourceItem(Server.HtmlEncode(NewItem.Text)); }
The code creates a ListItemCollection collection in code and populates it with sample data. Then, the code sets the SourceItems property to the collection.
Switch to Design view, double-click LoadFiles to create an event handler for the Click event, and then add the following highlighted code:
Protected Sub LoadFiles_Click(ByVal sender As Object, _ ByVal e As EventArgs) Handles LoadFiles.Click Dim path As String = Server.MapPath(Request.ApplicationPath) Dim files() As String = System.IO.Directory.GetFiles(path) Dim filename As String For Each filename in Files ListPicker1.AddSourceItem(filename) Next End Sub
protected void LoadFiles_Click(object sender, EventArgs e) { String path = Server.MapPath(Request.ApplicationPath); String[] files = System.IO.Directory.GetFiles(path); foreach(String filename in files) { ListPicker1.AddSourceItem(filename); } }
This code is similar to the code for AddItem, except that this code adds a list of files in the Web site root directory.
Switch to Design view, double-click ShowSelection to create an event handler for the Click event, and then add the following highlighted code:
Protected Sub ShowSelection_Click(ByVal sender As Object, _ ByVal e As EventArgs) Handles ShowSelection.Click Dim lItem As ListItem Dim selectedItemsString As String = "" For Each lItem in ListPicker1.SelectedItems selectedItemsString &= "<br>" & lItem.Text Next Selection.Text = selectedItemsString End Sub
protected void ShowSelection_Click(object sender, EventArgs e) { String selectedItemsString = ""; foreach(ListItem lItem in ListPicker1.SelectedItems) { selectedItemsString += "<br>" + lItem.Text; } Selection.Text = selectedItemsString; }
This code retrieves an object that is typed as a ListItemCollection object, reads each item in the collection, and then displays the results in Selection.
Switch to Design view, double-click ClearSelection to create an event handler for the Click event, and then add the following highlighted code:
Protected Sub ClearSelection_Click(ByVal sender As Object, _ ByVal e As EventArgs) Handles ClearSelection.Click ListPicker1.ClearAll() End Sub
protected void ClearSelection_Click(object sender, EventArgs e) { ListPicker1.ClearAll(); }
This code invokes the ClearAll method for the user control to remove all items from the TargetList.
Testing the Finished User Controls
Now, you can test your finished user control.
To test the user control
Press CTRL+F5 to run the page.
In the text box, type a value, and then click Add Item.
Repeat step 2 several times, until you have a selection of items in the user control.
Use the buttons to select one or more of the source items from the SourceList list, and then add them to the TargetList list.
Click Show Selection.
The TargetList list items are displayed in Selection.
Click Clear All.
Click File List.
The SourceList list now displays a list of file names.
In the user control, click Add to add several items to the TargetList list.
Try adding an item to the TargetList list that is already in the list.
The duplicate value is added.
Clear the Allow duplicates box, and then try adding duplicates again.
This time, the duplicates are not added to the TargetList list.
Click Show Selection.
The list of items in the TargetList list is displayed in the host page.
Next Steps
Although the control that you have created is not very complex, you have seen much of the basic functionality that you can build into a user control. Refining the control is largely a matter of revealing additional properties and methods that enhance what you can do with the control. Additional members might include the following:
Appearance properties.
You can create user control properties that let a user set the background, list size, and so on, for the control.
Note By default, the user control uses the current theme that applies to the child controls. For example, if you have a skin defined for a Button control, the buttons in your user control are displayed with that skin.
Data properties.
You can add properties that enable the user control to use a wider variety of data to display in the SourceList list. For example, you could add properties to set a dataset, data table, and data display field.
Functionality.
You can add more buttons and code to the user control to enable users not just to copy items from the SourceList list to the TargetList list, but also to move items—where the item is removed from the SourceList list as it is moved to the TargetList list. The control could then have buttons that could move the data back from the TargetList list to the SourceList list.
See Also
Tasks
How to: Convert Web Forms Pages into ASP.NET User Controls