Introduction
ASP.NET 2.0 introduced a plethora of new controls aimed at making life easier for developers. The other day I was using one of those new controls, the BulletedList, for the first time, to help me generate and write an unordered list to the page at runtime.
I could find very little real-world usage information about the new BulletedList control on the web, but fortunately it's a very easy control to master. It basically contains a collection of ListItem controls, one per bulleted item, and it can render each ListItem as plain text, a hyperlink to a URL, or as a hyperlink to initiate a PostBack. The DisplayMode property of the BulletedList control specifies how each of the ListItems will render.
The page I was constructing used the BulletedList to build a simple plain-text list, using code similar to this:
Source (.aspx file)
Code-behind file (VB version)
Code-behind file (C# version)
Author's Note: The code-behind files above use arrays to store the features and descriptions for the unordered list, for readability purposes. In production code, it is much better to use the new ASP.NET 2.0 generic classes for collections; in this case the Dictionary<TKey, TValue> class would be best.
To my surprise, the output made the bold text in my bullets look very bad:

All the angle brackets in the <strong> tags were being HTML encoded to < and >, which is normally a nice safety feature, but in this case I wanted to retain the angle brackets as-written so the page could see the HTML tags and render the bold text.
After I realized that the BulletedList control HTML encodes all plain text in each ListItem, I figured out fairly quickly that there was no option to output un-encoded (raw) text. A Google search on the topic only turned up one person who posted a usenet question about the same problem, without any replies.
So I did what any responsible .NET coder would do: I built my own control.
RichTextBulletedList Control
The RichTextBulletedList control uses the very common technique of inheriting all the properties and methods of the .NET control (in this case from the BulletedList control), and overriding the Render() method to control the output.
The RichTextBulletedList's Render() method calls the base class's Render() method, but instead of allowing the base method to write directly to the page, a new HtmlTextWriter is created and is passed to the base method, rather than passing the page's HtmlTextWriter.
Once the output from the base class's Render() method is captured, it is then modified to restore angle brackets, as well as quote characters. (In addition to the angle brackets, the base class also changes quotes (") into ", so we need to take care of that too, so attribute values in the HTML tags can be recognized as such.) Then, the modified output is passed to the page.
Below is the complete source listing for the RichTextBulletedList control. To create the control, create a new class file in the site's App_Code folder, and replace the default code in the new class file with the following:
RichTextBulletedList.vb (VB version)