asp tutorials, asp.net tutorials, sample code, and Microsoft news from 15Seconds
Data Access  |   Troubleshooting  |   Security  |   Performance  |   ADSI  |   Upload  |   Email  |   Control Building  |   Component Building  |   Forms  |   XML  |   Web Services  |   ASP.NET  |   .NET Features  |   .NET 2.0  |   App Development  |   App Architecture  |   IIS  |   Wireless
 
Pioneering Active Server
 Power Search





Active News
15 Seconds Weekly Newsletter
• Complete Coverage
• Site Updates
• Upcoming Features

More Free Newsletters
Reference
News
Articles
Archive
Writers
Code Samples
Components
Tools
FAQ
Feedback
Books
Links
DL Archives
Community
Messageboard
List Servers
Mailing List
WebHosts
Consultants
Tech Jobs
15 Seconds
Home
Site Map
Press
Legal
Privacy Policy
internet.commerce














internet.com
IT
Developer
Internet News
Small Business
Personal Technology
International

Search internet.com
Advertise
Corporate Info
Newsletters
Tech Jobs
E-mail Offers

HardwareCentral
Compare products, prices, and stores at Hardware Central!

Creating "Self Populating" Controls
By Luther Stanton
Rating: 4.0 out of 5
Rate this article


  • email this article to a colleague
  • suggest an article

    Background

    In this article we will look at combining two powerful elements of Microsoft's .Net platform: Custom Server Controls and Inheritance. We will develop a custom Web server control that inherits from the standard drop-down-list server control that is delivered with ASP.NET. The inherited control will fetch the data and populate the control based on parameters supplied by the developer; there will no longer be a need to write the actual data access code.

    The power of the .Net drop-down-list controls lies in the fact that they can bind to ADO.Net objects, such as DataSets or DataReaders. Once bound, the developer does not have to worry about writing the code to physically marshal the data elements from the DataSet or DataReader object into the control, which renders itself as an HTML select element. Instead, the developer only needs to specify the data source as well as the columns in that data source to be used as the value and display attributes of the select element. The control itself implements the required plumbing and rendering of the actual HTML that is sent to the browser. However, one thing that does consistently need to be written is the "glue code" to fetch the DataSet or DataReader from the database. While this can be completed through wizards within the VS.Net IDE, it is still a time consuming task to complete. By the end of this article, you will understand how to write a custom server control that derives from the default drop-down list, which has the glue code to fetch a DataReader based on specified properties embedded directly within the control, alleviating the need to write fetch code when populating the list control.

    Inheritance

    To accomplish our goal of developing the self-populating drop-down-list control, we will rely on inheritance. Inheritance is a common object-oriented concept that represents an "is a" relationship. A common example that is often used in object oriented (OO) texts deals with people and employees. The "is a" relationship can be illustrated as an "employee" is a type of "person". Now, let's assume that there exists a C# class called Person. This class exposes two properties, Name and SSN (Social Security Number). Now let's also assume that an employee C# class also exists and exposes two public properties as well, Manager and Salary. If we set up inheritance between the Person and Employee classes, that is the Employee class inherits from the Person class, the Employee class will also expose all the public properties and methods of the Person class. The employee class is also said to "derive" from the person class, In this example, the Employee class will have four properties, Name, SSN, Manager and Salary. Also, in this example, Person is called the base class and the Employee class is a derived class. Stated still yet another way, the Employee is a subclass and Person is the superclass.

    Once a class is derived, new properties and methods can be added to that class to extend the functionality of the base class. Elements from the base class can also be accessed from the derived class through the "base" C# keyword. Inheritance is a very powerful feature of .Net that can be used to the developer's advantage in numerous ways. This article shows just one way in which inheritance can be used to reduce the amount of required development. Although by no means an exhaustive discussion of all the OO concepts associated with inheritance, this brief introduction should be sufficient to understand and work through the concepts presented in the remainder of this article.

    Build a Data-Access Blueprint

    Before jumping right into developing the derived drop-down-list control, let's determine exactly how the glue code to retrieve the data to populate the control should look. We can then use this code to build a template that will be inserted into our derived control. Let's start by populating a simple drop-down-list control on a Web form.

    First, create a new ASP.NET Web Application project from the available Visual C# projects as in figure 1.

    Next, drag and drop a drop-down list control from the toolbox onto the default WebForm1.aspx webform the project wizard created for us. Let's change the name of the control to lstDemo, as shown in figure 2.

    Once the control is added to the page, we will add the required code to populate the list box, as shown in figure 3. We only want the list box populated when the page is first loaded and not when the page is posted back to itself. This is accomplished by checking the value of IsPostBack and only populating the list box when the IsPostBack value is false.


    Figure 3 - Code listing to fetch the data and populate the drop-down-list control

    A list box can bind to either a DataSet or a DataReader. I chose the latter in this scenario for better performance. The rich functionality delivered by a dataset will not be used to simply populate a drop-down-list object; performance is improved through using the smaller, simpler DataReader object. Also note that, for this example, I am using a SqlDataReader class and not an OLEDBDataReader class. This decision will limits access to only SQL data sources, however, performance is optimized. If you need to connect to databases other than Microsoft SQL then go ahead and use and OLEDBDataReader class instead. Do not forget to add the necessary using directives for the appropriate data client namespaces, as default ASPX pages only include the System.Data namespace.

    The remainder of the code is straight forward. I create the connection and command with the using statement. This statement will automatically call the Dispose method of the declared object after the block of code delineated by the using statement is executed. Once the command and connection are created and defined, we simply need to populate the DataReader object, selecting the author id and last name from the authors table in the pubs database. Once the data is retrieved, we need to set the data source, the fields from the DataReader that should be used value and text fields and then finally bind the data source to the drop-down list control. Once you have the code entered, compile the project. Running the code should generate an HTML select element with the author id column as the option value and the author's last name as the display text within the drop-down list.

    Define Needed Properties

    Now that we have a working example to use as a template, we can develop a plan of how to proceed with development of our derived control. The first step is determining what should be generalized and collected as parameters and what should be embedded in the control. At first glance the following items are likely candidates to be passed as parameters:

    • Connection String
    • Database Table
    • The value column and display text column for each option sub-element of the HTML select element

    We need a connection string so that we know which database to connect to. This will most often be stored in the Web.Config and possibly cached in an Application level variable somewhere, so we should be able to capture this value easily.

    The Database Table will be used within the select statement. Since the select statement is simple, we can dynamically build the select statement from the database table and the fields specified for the value and display text values.

    The value and display text columns also just happen to be properties of the control from which we will inherit; therefore, we can just "borrow" them from our parent control!

    The only thing that we have not accounted for as of yet is error handling. When we start accepting user input such as the connection and table column names, we must gracefully handle any possible errors that may arise, such as a bad connection string or missing parameters. We could simply choose not to handle the error and let it propagate back to the caller such as the default drop-down list control does. This would then require the end user to wrap our control in a try catch block to handle errors effectively. However, one of the benefits of deriving a new control is that we can add some niceties such as self-contained error handling that is trapping thrown errors and converting them into clean text messages for our caller. This is completely optional and can be left out if so desired, instead letting the exception framework built into .Net do its work.

    So without further delay, let's get to work building the derived control. The first step is to create a new Web Control Library Visual C# Project. Name the project mycoServerControls. It is often a good idea to prefix all control names with your company name for any type of production control. For this exercise, I will use "myco" as a company prefix.

    There are a couple of housekeeping details that need to be addressed prior to adding the glue code to fetch the data to populate control:

    • Change namespace of the control from mycoServerControls to mycoServerControls.DropDownList as in figure 4.


      Figure 4 - Change the namespace for the control

    • Change the name of cs file from WebCustomControl1 to mycoServerControls.DropDownList as in figure 5.


      Figure 5 - Change the file name to match the namespace

    • Change the name of the class from WebCustomControl1 to mycoDropDownList and change the inheritance of the control from System.Web.UI.WebControls.WebControl to System.Web.UI.WebControls.DropDownList as in Figure 6.


      Figure 6 - Setting the class name and inheritance

    • Add the necessary references pull in the SQL client classes and namespace as in Figure 7.

    What's in a Namespace?

    Before moving on to examine the code that is included in a default Web Control Library project, a few words about namespaces may clarify why I suggested the changes in file name and namespaces. These changes are only suggestions and moving forward with the default namespaces / filenames will not have any negative impact on developing a fully functionally server control. However, making the changes may simplify maintenance and implementation in an enterprise environment down the road.

    I always rename my C# source files to the namespace that they contain. Yes, this will force you to limit files to contain a single namespace, but I feel this helps you logically divide your work within a project. If a single project contains multiple namespaces, additional source files can be added to a project easily enough, and there still exists a clean, intuitive division of source code within the project. Also, shorter source files are often easier to work with. It also helps to identify where the source code for a particular namespace resides, as you now do not have to open each file to look at the namespace contained within.

    I also suggested renaming the namespace for the control from mycoServerControls to mycoServerControls.DropDownList. This is simply to narrow down the scope of the source contained in the namespace. Eventually, you may decide to develop derived controls for text box controls. Perhaps there will be two: one to validate numeric data entry and another to validate string entries. Furthermore, you may wish to develop another derived DropDownList control that uses stored procedures instead of dynamic SQL. Had we not changed the default namespace for the dropdown list control, we could have all four controls contained in the single namespace mycoServerControls, and if we follow the file naming conventions outlined in the previous paragraph, we could have all four controls contained in a single file. As you can imagine, as additional control types are derived, the single source code file solution could get unmanageable rather quickly.

    However, by making the namespace more descriptive, that is creating mycoServerControls.DropDownList and mycoServerControls.TextBox namesapces, we can now create individual source code files that only contain a single type of control. This leads to a much more organized and logical approach to grouping classes and functionality within .Net. The .Net framework is designed to be extended by developers as needed. Looking at how the base .Net framework namespaces are set up and trying to model that structure with your own custom namespaces will result in a professional toolkit being developed over time that is usable across the enterprise without namespace clashes. It is important upfront to define a namespace strategy and move forward with it. Not completing this step early in the adoption of .Net could lead to complications and a large namespace reorganization project later on down the road.

    Setting the Default Property and ToolboxData info By virtue of selecting a Web Control Library project, the VS.Net IDE adds some "default" code into the project for us. The first block of code to examine is shown in Figure 8.


    Figure 8 - DefaultProperty / ToolboxData code for Web Control Library projects

    This line of code sets up two things, the default property for the control and the toolbox / tag information. The default property must correspond to a property of the control. ToolboxData specifies name that will appear in the Toolbox for this control and the default class name (in this example WebCustomControl1) for the tags that will be inserted into the ASPX pages when this control is added to a WebForm. The {0} in the format string will be replaced by the tag prefix. Both instances of WebCustomControl1 should be replaced with the new class name, mycoDropDownList. Additionally, we will not exposing a property named "Text" on this control, so the default property should be changed to "ConnectionString". Both changes are shown in figure 9.


    Figure 9 - Changes to DefaultProperty / ToolboxData code snippet

    Control Properties


    The next snippet of code to review is listed in Figure 10. This section of code shows a public property declaration for a control. There are a few attributes that we need to look at. The first is 'Bindable(true)'. This attribute is used during design time to indicate to the IDE whether or not the property can be data-bound to a valid source. The next is Category("Appearance"). This attribute controls what category the IDE will place the property under within the Property designer. You can use one of the default categories, such as "Appearance" or "Data" or enter your own custom category. The final attribute DefaultValue simply provides a means to enter a default value for the property. We need to either remove or rename the Text property and add the following properties to the control:

    • ConnectionString
    • SourceTable
    • ErrorMsg

    The code for these three properties is shown in Figure 11. Note that the ErrorMsg property is implemented as read only.


    Control Methods

    The last piece of code added by the IDE is a sample implementation of the Render method. Notice that the method declaration has the keyword override. Our parent class has a method named Render as well. It is marked as overridable in the superclass, meaning that a derived class can expose a method by the same name. When a derived class does implement a function with the override keyword, it means the derived class will handle this functionality and the parent's implementation of the method will not be invoked unless it is specifically called by the subclass. In essence, the child class's behavior will override that of the parent. Because we have no reason to change how the control is rendered -- after all we only desire to populate the control -- we can remove this method completely. That is part of the beauty of inheritance. Anything we do not implement through method overrides will be handled by our parent; we are simply adding some specialized functionality.

    The only method that we will expose will fetch the data from the database and will bind the resulting DataReader to the drop-down-list control, i.e., our parent. We could simply override our parent's DataBind method; however, users could no longer use our control as a default drop-down list. Changing the default behavior of the DatBind method will not allow users to write their own data fetch code and use our control as a default drop-down list. This would limit the use of our control and actually decrease functionality / flexibility. So we will add a new method, Populate() that will fetch the DataReader and then call DataBind on our parent to populate the drop-down list. The completed method is shown in Figure 12.


    As is shown in the code listing for the Populate method, we can access properties and methods of our parent control using the "base" C# keyword. All SQL code is wrapped in a try catch block. In the event the SQL access code throws an error, the Populate method returns false and the ErrorMsg property will be set.

    The remainder of the code is identical to the "template" data access code we developed and tested earlier. Everything should build with no errors and no warnings. Once a release build is completed, the DLL will need to be placed into the bin folder of any project where the control will be used, unless the derived control's DLL is placed in the machine's Global Application Cache.

    Using the Control

    Let's return to our earlier Web project, the one in which we hand wrote the data fetch code. Make sure that the new contol's dll is placed in the \bin folder of the application. Once in the bin folder, we need to link the control with VS.Net. We start by setting a reference to the control from the toolbox. The following steps accomplish this

    • Right click on the toolbox and select 'Customize Toolbox...' as in Figure 13. If you would like the control to appear in a specific area of the toolbox, such as WebForms, Data or General, ensure you right click in the area of the toolbox.


    • From the Customize Toolbox dialog, select the .Net Framework Components tab, click the Browse button and find the control's dll (Figures 14 and 15).


      Figure 15 - Selecting the control's executable file

    Once a reference from the control is established, the control will appear in the selected area of the toolbox, as shown in Figure 16.


    Figure 16 - Control appears

    Now that the control is in the toolbox, it can be simply added to any WebForm just as any other control is added. Figure 17 shows a combination of standard Data Drop Down properties as well as some of the new properties were added to our derived control appearing in the Data section of the Property window of the VS.Net IDE. The properties are set to populate the drop-down list with the same data that we are manually fetched in the web app earlier.

    Once the properties are set, we need to add the code to the Page_Load event of the ASPX page to populate the control. Since this method returns a result, we also need to check the result and display the value of the ErrorMsg property if an error does occur. I chose to display the message through a label control I added to the page. Figure 18 shows the new code needed to populate the drop-down list, all of two lines of code!


    Figure 18 - Code required to populate the derived control

    When the page is compiled and run, we can see both controls side by side displaying the same data, as in Figure 19.

    The last thing that remains is to ensure that the error handling works as expected. In order to test this, change the value of the DataTextField property to an invalid value and re-run the application, as shown in Figure 20. The error from the control should be displayed in the label on the page as in Figure 21.


    Figure 20 - Testing the control's error handling

    Summary

    This article has reviewed combining two powerful .Net features, inheritance and server controls to create a self populating drop-down-list control. Data driven drop-down lists have become a fact of life in today's world of data centric web development. We looked at how we can significantly reduce the amount of repetitive code that we need to write, test and maintain on every project. During the building of the control, we reviewed a means to trap and handle errors instead of letting them propagate back to the caller. Additionally, we also looked at the importance of namespaces and how to maximize their use in developing reusable code for use throughout the enterprise.

    This article can serve as a jumping off point for additional enhancements, more robust error trapping, ensuring users enter both value and text fields, or implementing additional properties and perhaps methods to support the use of stored procedures instead of / in addition to embedded SQL. This article has only scratched the surface on what can be done with extending or creating new server controls and still we created a reusable component that fulfills a real development need. Because of inheritance, we did not have to worry about things such as rendering and view state, we simply allowed our parent to handle these details for us. However, it is in these areas where server controls can flex quite a bit of muscle. Server controls provide a powerful paradigm that promises to allow developers to implement even richer user interfaces for web applications. I hope this article has generated enough interest so that you want to delve further into the realm of server controls.

    Download source code for this article

    About the Author

    Luther Stanton is a Principal Consultant and Application Development Practice Lead with Intellinet Corporation, based in the Atlanta, GA area. Intellinet, the Southeast's only triple Microsoft Gold Certified Consulting Partner (Enterprise Systems, Security and eCommerce), provides infrastructure and application development consulting services through the southeast.

    Luther resides in Locust Grove, GA, with his wife, Heidi. He has actively developed Microsoft centric applications for over seven years and has worked with .Net since Beta 1. Before joining Intellinet, Luther worked for other consulting organizations in the Atlanta area as well as Deloitte & Touche Consulting Group. He also served as a Communications Officer in the US Army. Luther can be reached at luthers@intellinet.com.

  • Rate This Article
    Not HelpfulMost Helpful
    1 2 3 4 5
    Other Articles
    Apr 21, 2004 - Creating a Web Custom Control
    Conrad Jalali shows how to build Web custom controls by creating one that displays checkboxes in a categorized, hierarchical view.
    [Read This Article]  [Top]
    Mar 15, 2004 - Creating a Popup Date Picker
    Conrad Jalali shows how to extend the functionality of the ASP.NET Calendar control to remove some of the annoying postback delays that occur when populating a text box with a date from a popup calendar.
    [Read This Article]  [Top]
    Oct 23, 2003 - Creating a Custom .NET Web Control With Events
    This article covers some of the essentials of building reusable Web controls. Learn how to create a Web control and its custom events and event arguments, as well as how to use the control properly within a page.
    [Read This Article]  [Top]
    Aug 12, 2003 - Creating a Generic Pager Control
    ASP.NET provides only one control that supports paging, the DataGrid. Tomasz Kaszuba shows how to build and implement a custom pager for different controls that change depending on the data source or presentation.
    [Read This Article]  [Top]
    Jun 10, 2003 - Hosting .NET Windows Forms Controls in IE
    Windows Forms within Web pages work in a manner similar to Java applets. Thiru Thangarathinam shows how to host Windows Forms controls in Internet Explorer and how to utilize .NET Code Access Security to configure what the control can do when running within the browser.
    [Read This Article]  [Top]
    May 6, 2003 - Building a Simple Mask Control
    James Culshaw shares his experiences building his first working custom control, a basic mask control that allows input of time values, and offers advice and tips to those just starting out.
    [Read This Article]  [Top]
    Mar 3, 2003 - Creating a Server Control for JavaScript Testing
    Learn how to create an ASP.NET server control that detects if a browser supports JavaScript AND if JavaScript is enabled.
    [Read This Article]  [Top]
    Jan 21, 2003 - Protecting Users from Suspect Textual Data
    Learn the ins and outs of composite controls by creating an application that prevents users from submitting offending text.
    [Read This Article]  [Top]
    Nov 26, 2002 - Introduction to the .NET Speech SDK
    Rob Chartier offers a tour of the .NET Speech SDK Beta 2 and its use of the industry specification SALT. The article shows you how to create a basic speech-enabled Web user control.
    [Read This Article]  [Top]
    Apr 30, 2002 - Building ASP.NET User and Server Controls, Part 2
    Solomon Shaffer explains custom controls, describes the complexities and issues surrounding building such controls, and walks through a useful example.
    [Read This Article]  [Top]
    Mailing List
    Want to receive email when the next article is published? Just Click Here to sign up.

    Support the Active Server Industry

    internet.comearthweb.comDevx.commediabistro.comGraphics.com

    Search:

    Jupitermedia Corporation has two divisions: Jupiterimages and JupiterOnlineMedia

    Jupitermedia Corporate Info

    Legal Notices, Licensing, Reprints, Permissions, Privacy Policy.
    Advertise | Newsletters | Tech Jobs | Shopping | E-mail Offers