
SP.NET is a terrific platform for Web applications. That does not mean that tricky coding is always one or two clicks away within a dockable and resizable Visual Studio .NET dialog box. Tricky solutions require tricky coding, just the kind of features that a wizard-driven environment and a general-purpose framework can't provide. In this article, we'll tackle five ASP.NET features that require wicked and creative code.
Have you ever heard about the "real programmer?" The real programmer is someone who makes a living putting one keyword after the next, abiding by some sort of syntax and semantics. Being strongly results-oriented, the real programmer gained a reputation for hating all the bells and whistles that inevitably surround any software technology. Wizards, black box components, and data binding? No, thank you. The real programmer makes a point of writing hundreds of lines of code to get full control over each execution step.
Frankly, I've found myself in the position of the real programmer more than once, especially regarding data binding. As a real programmer, I never used old Visual Basic data-bound controls. If you ever experienced the data-bound controls of early versions of Visual Basic, you know why. But the advent of the .NET Framework changed things quite a bit. The .NET Framework comes with a powerful data binding mechanism implemented for both Windows Forms and Web Forms.
Unfortunately but reasonably, the set of ASP.NET data-bound controls just don't cover all possible scenarios; you can have automatic binding between a data source and a list of check boxes or radio buttons. But if you're looking for a data-bound bulleted or numbered list of strings, prepare to face disappointment.
I'm not sure how you feel about that, but I craved a BulletList control for a while. Then, I made the decision to build it myself. Quite surprisingly, it wasn't too difficult. It is probably a task within the reach of any programmer and not just "real programmers."
1. Building a Bulleted List Control
The
BulletList control can be built starting from the
WebControl class. This class provides a default implementation for several handy UI properties, such as
Font and
ForeColor. By inheriting from WebControl, you don't have to worry about common UI-related properties and can focus on the more specific attributes of the control.
The
BulletList control needs at least four properties, as listed in
Table 1.
Table 1: These are the properties of the BulletList control.
Property
|
Description
|
BulletListType
| Indicates the type of bulleted list. Feasible values are defined in the BulletList enumeration: UL or OL.
|
DataSource
| Gets and sets the data source associated with the control
|
DataTextField
| Gets and sets the name of the data source field to be used to fill the list
|
Items
| The collection of strings that represents the items added to the list
|
The
Items property has a double role. For one thing, it is the internal buffer in which the data-bound information is parked before it is rendered to HTML. Because the property is marked as public, you can also use it to manually add strings of text to the list. This code snippet shows how to add extra items at the bottom of the list created after the data source.
list.Items.Add("Plus this one!");
The
DataSource and the
DataTextField properties let you extract a particular column of data out of an ADO.NET container. The use of these properties is in no way different from analogous properties defined in other list-bound classes (e.g., CheckBoxList). The typical use you can make of them is shown in this next snippet.
// Run the query
SqlDataAdapter adapter;
string cmd = "SELECT * FROM employees";
string conn = "SERVER=...;DATABASE=...;UID=...;";
adapter = new SqlDataAdapter(cmd, conn);
// Bind the control
DataTable table = new DataTable();
adapter.Fill(table);
bList.DataSource = table;
bList.DataBind();
The control also needs to override the
DataBind method inherited from the
Control class. When the
DataBind method is called, the control loads the bound data source into the Items string collection. During the
Render method (another overridden method), the control builds the bullet list, mixing together HTML tags and text strings. In HTML, you can have two types of lists: the classic bulleted list or a numbered list. In the former case, you create it using the
<ul> tag; for the latter case, use the
<ol> tag. Nested within those elements, there is one
<li> tag per each item to display.
The control's programming interface allows you to choose the type of bulleted list through the following enum type:
public enum BulletType
{
UL,
OL
}
A value of type
BulletType is assigned to the
BulletListType property. An enum type cannot be a collection of strings; only basic types can be used, such as int or double. By giving the entries in the enumeration the same mnemonic names of HTML tags, you can easily associate each of them with the correct string using the
ToString method.
Listing 1 shows how to render the BulletList control to HTML, based on the value of the
BulletListType property.
The full source code of the BulletList control is shown in
Listing 2. Notice the technique used to generate the HTML for the control. The Render methodthe procedure that calls into the
CreatePanel method shown abovegets an HTML
TextWriter object from the .NET Framework and sends text to it. You can implement the Render method in such a way that the code simply outputs text to the stream; alternatively, you can use a temporary instance of a control, configure it through properties, and then render it. The gain is that you end up with code far easier to read and maintain. This technique is frequently used within ASP.NET itself.
To add IntelliSense support to the HTML view of the visual designer, you need to provide the schema of the control: an XSD file.
|
|
Regarding
Listing 1, the technique based on temporary controls might seem overkill. The following code would have worked great as well. Judge for yourself.
output.WriteBeginTag("ul");
output.Write(HtmlTextWriter.TagRightChar);
foreach(string elem in Items)
{
output.WriteBeginTag("li");
output.Write(HtmlTextWriter.TagRightChar);
output.Write(elem);
output.WriteEndTag("li");
}
output.WriteEndTag("ul");
Figure 1 shows the BulletList control in action based on this next bit of code.
<%@ Register TagPrefix="expo"
Namespace="CodeMag.Controls"
Assembly="BulletList" %>
<form runat="server" ID="Form1">
<expo:BulletList runat="server" id="bList"
DataTextField="lastname" _
BulletListType="ul" />
</form>