![]() |
Web Development »
Custom Controls »
General
Intermediate
License: The Code Project Open License (CPOL)
Creating a BulletedList control to replace the asp:BulletedListBy bgs264I needed a simple control to display a bulleted list based on a strongly typed list of strings. |
VB (VB 8.0), HTML, XHTML, .NET (.NET 2.0), ASP.NET, WebForms, Dev
|
|
Advanced Search |
|
|
|
||||||||||||||||
I wanted to display a bulleted list of items (<li> tags rendered within a <ul> tag) on a web page, based on a strongly typed list of string objects which I had gathered from some data source.
I noticed that there is a BulletedList control available in .NET, so I tried it. I set the DataSource to my List(Of String) and called DataBind().
It worked — sort of. The bulleted list displayed the content of each string in my list, but it insisted on HTML-encoding every item. As I had hyperlinks within the list (<a href="somepage.htm">click me</a>), it was rendering to the output stream as <a href="somepage.htm">click me</a> such that I did not get a hyperlink in the page. Frustrating. Thanks for that auto-encoding, Microsoft!
I spent a little while looking into the BulletedList control and Googling this problem, but it seemed to be just a "feature" of the BulletedList which wasn't controllable (I might be wrong!). Instead of using the asp:BulletedList, I wrote a Repeater to render out the items, but it looked messy in the .aspx page, and I wasn't really happy with it — I wanted a control as I wanted to use it in a few places — a Repeater might have been OK for just one instance, but not several.
I threw my hands up at another short-sighted "feature" of the framework, and went out to enjoy a meatball sub and oatmeal and raisin cookie, with a diet coke on the side.
In the sandwich shop, whilst watching the July rain driving at the pavements outside, I decided to just write a control myself to do what I wanted — I thought I had quite a basic requirement here, and decided that in the time I spent Googling for the solution, I could have solved it myself. Now, all I had to do was get back across the road to the office, in a short sleeved shirt, in the pouring rain. I love Manchester.
My first step was to create a .vb class file, which I called BulletedList.vb. I put the class inside a namespace to make it easy to register it later on, and made it inherit from Control.
Next, I created a property called "Items" which provides read/write access to the list of items I wanted to render. Remember, I wanted to use a strongly typed list of strings. I save the items within the ViewState of the control.
Public Property Items() As List(Of String)
Get
If IsNothing(ViewState("Items")) Then
' Instantiate the list of items to a new list; which will allow us to do ".Items.Add" from elsewhere in code without
' having to worry about null values checks.
ViewState("Items") = New list(Of String)
End If
Return DirectCast(ViewState("Items"), List(Of String))
End Get
Set(ByVal value As List(Of String))
ViewState("Items") = value
End Set
End Property
So, I can now hold a list of the strings I want to display on the page. The next thing is to tell the control how it should render them. I simply overrode the "Render" method of the control, and provided some custom logic:
Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter)
' Only output something if there are items in the collection:
If Items.Count > 0 Then
' Output start tag <ul>
writer.RenderBeginTag(HtmlTextWriterTag.Ul)
' Output all the items
For Each s As String In Items
writer.RenderBeginTag(HtmlTextWriterTag.Li)
writer.Write(s)
writer.RenderEndTag()
writer.WriteLine()
Next
' Output end tag </ul>
writer.RenderEndTag()
End If
MyBase.Render(writer)
End Sub
As you can see, it is reasonably straightforward. If there are any items in the list, then I create the opening <ul> tag, and then write out each item contained within <li> tags. Once all the items have been written, I close the <ul> tag, and call the base Render method (it doesn't actually do anything, it's just there for completeness).
I appreciate the sentiment of HTML-encoding the text from a security point of view; that HTML data retrieved from data stores (especially where that data has come from an unknown source) should always be HTML-encoded before it is displayed out onto web pages to help prevent injection attacks.
For this reason, I provided another property, EncodeHtml, to allow the user of the control to decide whether they want the output to be encoded before it gets rendered. The property is a simple boolean value saved in the ViewState:
Public Property EncodeHtml() As Boolean
Get
If IsNothing(ViewState("EncodeHtml")) Then
Return False
Else
Return DirectCast(ViewState("EncodeHtml"), Boolean)
End If
End Get
Set(ByVal value As Boolean)
ViewState("EncodeHtml") = value
End Set
End Property
I then amended the Render method to take account of this property, and HTML-encode the text if desired. This concludes the control's implementation.
Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter)
' Only output something if there are items in the collection:
If Items.Count > 0 Then
' Output start tag <ul>
writer.RenderBeginTag(HtmlTextWriterTag.Ul)
' Output all the items
For Each s As String In Items
writer.RenderBeginTag(HtmlTextWriterTag.Li)
If EncodeHtml Then
writer.Write(HttpContext.Current.Server.HtmlEncode(s))
Else
writer.Write(s)
End If
writer.RenderEndTag()
writer.WriteLine()
Next
' Output end tag </ul>
writer.RenderEndTag()
End If
MyBase.Render(writer)
End Sub
Using the code is simple. First, register the control at the top of the .aspx file:
<%@ Register TagPrefix="SCC" Namespace="SCC.WebUserControls" %>
Next, add the control into the .aspx markup where you want the bulleted list to appear:
<SCC:BulletedList ID="blHyperlinks" runat="server" /> <!-- Render all items "as-is" -->
<SCC:BulletedList ID="blSafeHtml" runat="server" EncodeHtml="true" /> <!-- Encode HTML -->
Finally, in Page_Load or similar, bind the control to your desired list of strings:
Dim Hyperlinks As New List(Of String)
Me.blHyperlinks.Items = Hyperlinks
and that's it. "Should just work".
The downloadable file contains a fully XML-commented code listing for your perusal. Any comments welcome (particularly, if you can tell me whether the asp:BulletedList can be configured to not HTML-encode the text that you bind to it from a strongly typed list of strings!).
| You must Sign In to use this message board. | |||||
|
|||||
|
|||||
|
|||||
General
News
Question
Answer
Joke
Rant
Admin
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 17 Jul 2008 Editor: Sean Ewington |
Copyright 2008 by bgs264 Everything else Copyright © CodeProject, 1999-2009 Web10 | Advertise on the Code Project |