Click here to Skip to main content
Click here to Skip to main content

Rich List Controls in ASP.NET

By , 1 Nov 2005
 

Introduction

This article chronicles my quest to both improve upon the existing ASP.NET list controls but also to learn about some of the hidden mysteries of Custom Web Controls.

Background

Custom Web Controls have been one of my favorite features of the ASP.NET framework from the time I first started using it three years ago. I had been doing web development for many years before that and the idea of being able to encapsulate my logic into controls was very appealing. The largest problem I kept running into when developing my own controls was the poor documentation on some of the advanced features. I looked at the simple controls I was developing, then I looked at rich controls such as the DataGrid, and I noticed a large disparity. I found many articles on custom web controls and even read this book. Although these resources were helpful, they did not reveal the hidden secrets of the Microsoft web controls.

This article explains some of the things I learned while developing my own version of the ASP.NET list controls. I found the individual list items (RadioButton and CheckBox) to be very rich but when placed inside of their respective list controls (RadioButtonList and CheckBoxList) they list a lot of functionality. I wanted to be able to customize the styles for the individual list items and to have tooltips as well. I did, however, really like some of the features that the list controls afforded me such as data binding and layout control. When I discovered Lutz Roeder's Reflector, I decided to pick apart the Microsoft controls in an effort to write my own.

Notable Findings

Some of the code used in the ASP.NET list controls is marked as internal so us lowly non-Microsoft developers do not have access to them. To do this, I simply copied their code and made it public. There were some parts which were public but I had never seen documented. One such class is the interface System.Web.UI.WebControls.IRepeatInfoUser. This class facilitates the layout control for any repeating list of items. The most notable part of the interface is:

public void RenderItem(ListItemType itemType, int repeatIndex, 
  RepeatInfo repeatInfo, HtmlTextWriter writer);
This code is called for each item in the list so that you can render each item yourself. Here is the complete code for implementing this method in my RadioList Control:
public void RenderItem(ListItemType itemType, int repeatIndex, 
  RepeatInfo repeatInfo, HtmlTextWriter writer)
{
  RadioButton button1 = new RadioButton();
  button1.Page = Page;
  button1.GroupName = UniqueID;
  button1.ID = string.Concat(ClientID, "_", 
    repeatIndex.ToString(NumberFormatInfo.InvariantInfo));
  button1.Text = Items[repeatIndex].Text;
  button1.ToolTip = Items[repeatIndex].ToolTip;
  button1.Attributes["value"] = Items[repeatIndex].Value;
  button1.Checked = Items[repeatIndex].Selected;
  button1.TextAlign = TextAlign;
  button1.AutoPostBack = AutoPostBack;
  button1.TabIndex = radioButtonTabIndex;
  button1.Enabled = Enabled;

  foreach(string key in Items[repeatIndex].Attributes.Keys)
  {
    button1.Attributes[key] = Items[repeatIndex].Attributes[key];
  }

  button1.RenderControl(writer);
}
      
This code basically just using the information from the Items collection to build a RadioButton control and then to render it. It is that simple!

RichListItems

Most of the changes that I made were to the System.Web.UI.WebControls.ListItem class. I made my own version called RichListItem. I added a property of type System.Web.UI.WebControls.TableItemStyle called Style. This allows for each list item to have its own style settings. The attributes on this property are important when it comes to the behavior of this class being persisted when using the controls in design mode.

[
  Category("Behavior"),
  Description("The Style of this item"),
  DesignerSerializationVisibility(DesignerSerializationVisibility.Content),       
  NotifyParentProperty(true),
  PersistenceMode(PersistenceMode.Attribute)
]
      
By using PersistenceMode.Attribute, the style information for each list item is persisted as attributes (using the '-' naming convention). The DesignerSerializationVisibility.Content is what tells Visual Studio to persist the styles as content.

Besides adding styles to the list items, I added the ToolTip property. In order to do this, I had to change the ViewState persistence to save the ToolTip along with the Text and the Value of the list item.

internal object SaveViewState()
{
  if(misc.Get(TEXTISDIRTY) && misc.Get(VALUEISDIRTY) && misc.Get(TOOLTIPISDIRTY))
  {
    return new Triplet(Text, Value, ToolTip);
  }
  else if (misc.Get(TEXTISDIRTY) && misc.Get(VALUEISDIRTY))
  {
    return new Pair(Text, Value);
  }
  else if (misc.Get(TEXTISDIRTY))
  {
    return Text;
  }
  else if (misc.Get(VALUEISDIRTY))
  {
    return new Pair(null, Value);
  }
  else if(misc.Get(TOOLTIPISDIRTY))
  {
    return new Pair(ToolTip, null);
  }
  return null;
}

internal void LoadViewState(object state)
{
  Pair pair;
  Triplet triplet;
  if (state == null)
  {
    return;
  }
  if ((state as Triplet) != null)
  {
    triplet = ((Triplet) state);
    Text = (string)triplet.First;
    Value = (string)triplet.Second;
    ToolTip = (string)triplet.Third;
  }
  else if ((state as Pair) != null)
  {
    pair = ((Pair) state);
    if (pair.First != null)
    {
      if(pair.Second != null)
        Text = (string)pair.First;
      else
        ToolTip = (string) pair.First;
    }
    if(pair.Second != null)
    {
      Value = ((string) pair.Second);
    }
    return;
  }
  this.Text = ((string)state);
}
    
An in depth explanation of state management is beyond the scope of this article but note how the LoadViewState and the SaveViewState methods compliment each other. In the case of the RichListItem, there are three possible values to be persisted: Text, Value, and ToolTip.

API Changes

There are some breaking changes as far as making the RichListControls backwards compatible with the ASP.NET list controls. There is still a base class, RichListControl, which provides the basis for all list controls. I have added another level of inheritance in between the list controls and the base RichListControl class. I broke them out into two different types: SingleSelectListControl and MutipleSelectListControl. This allows list controls which allow only one item to be selected to have properties for SelectedIndex, SelectedItem, SelectedValue, and SelectedText. List controls which allow multiple items to be selected have properties for SelectedIndices, SelectedItems, SelectedValues, and SelectedTexts. I have added a property to the base RichListControl called HasSelection which indicates whether or not any items are selected in the list. Here is an example of a possible use of these properties:

if(list.HasSelection)
{
  foreach(RichListItem item in list.SelectedItems)
  {
    lblSelection.Text += String.Format(" {0}", item.Text);
  }
}
else
{
  lblSelection.Text = "No Selection";
}
      

Using the code

The RichListControls are used in the exact same way as the traditional ASP.NET list controls. Note the Style and ToolTip attributes below.

<%@ Register TagPrefix="List" Assembly="RichListControls" 
  Namespace="RichListControls" %>
<List:RichRadioButtonList id="list" runat="server">
  <Items>
    <list:RichListItem ToolTip="This is not that many miles" 
        Style-Font-Italic="True" Style-ForeColor="Green"
      Value="0">0 - 15</list:RichListItem>
    <list:RichListItem ToolTip="Most People Drive at least this much" 
          Value="5">15 - 30</list:RichListItem>
    <list:RichListItem Style-Font-Bold="True" Style-ForeColor="Firebrick" 
         Style-BackColor="LightYellow"
      Value="10">30+</list:RichListItem>
  </Items>
</List:RichRadioButtonList>
    

Points of Interest

There are a couple of helper classes I used which are worth noting. First, there is StyleHelper which is used by the RichDropDownList to convert a System.Web.UI.WebControls.Style to a string that can be used in an HTML style attribute. Most of this code is taken straight from internal methods in the System.Web dll.

There is also DataSourceHelper which is used in databinding. All of the code in this is taken from the System.Web dll.

History

  • 9/9/2004 - Initial release.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Luke Foust
Web Developer
United States United States
Member
Luke Foust is a software developer from San Diego, CA.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionDatabinding Questionmemberrbscene20 Sep '07 - 8:48 
How do I set the ToolTip Attribute and the Style Attribute while DataBinding to my DataSource for a CheckBoxList, using this control.
 

chkMyService.DataSource = DS.Tables(0)
chkMyService.DataTextField = DS.Tables(0).Columns("ser_Name").ToString
chkMyService.DataValueField = DS.Tables(0).Columns("ser_ID").ToString
chkMyService.DataBind()
 
Also is there an option to Set a Checkbox as disabled?
 
Thanks,
 
Robert
Generalddl OnSelectedIndexChanged not firing.memberrymos15 Aug '07 - 9:20 
Hey,
 
Thanks a ton for this. It's really helped me out.
 
One dropdownlist issue i'm having is that the OnSelectedIndexChanged event is not firing.
 
The "OnLoad" fires.
 
Any ideas?
 
P.S. The AutoPostBack is set to true
QuestionWith RichCheckBoxList how do I select/check at server sidemembernitadx2 Jan '07 - 0:52 
Hi,
 
I'm using your control to list items from a database, I can list them with no problems, but I can't check items at server side. I'm using RichCheckBoxListObject.Item[i].selected = true within the ItemCreared method, is this the correct way of doing this.
 
Kind regards
GeneralXML DataBinding [modified]membermichel petrovic19 Sep '06 - 21:54 
Hello
I would like to bind the DataBoundCheckBoxList with an XML DataSource.
Currently I'm using an asp:repeater in which I have the following databinding syntax:
 
<asp:Label ID="OperatorIDLabel" runat="server" Text='<%# ((XmlNode)Container.DataItem).Attributes["Id"].Value %>' Visible="false" Width="0px" />
 
I tried to put it into your attribut DataTextField but it isn't supported: the compiler gives me an error.
 
Is it possible to do it?
 
Thanks
 

-- modified at 9:06 Wednesday 20th September, 2006
 
Michel

GeneralSelected Index Changed not calledmemberDan Pupek15 May '06 - 5:31 
The reason Post Back doesn't seem to work is that the SelectedIndexChnged event is never invoked. Any reason why?
GeneralRe: Selected Index Changed not calledmemberMohamed Elzahaby29 May '06 - 14:18 
Make sure that you changed the control to be AutoPostBack = True
GeneralDatabindingmemberLogan57354 Apr '06 - 10:44 
I am using MultipleSelectListControl. I cannot bind a dataview datasource to it. When I change the control to RichDropDown, no problems.
 

GeneralNo PostBack!!!membergooseman9 Jan '06 - 9:04 
I've been trying to get this code to work with it firing the PostBack routine in the CheckBoxList. Foolishly, I first converted the code to VB.Net and failed. Then out of frustration I loaded the demo and modified the CheckBoxList to write "blah" on a Change of Index but again no dice! Is it just that I'm at the end of the day or is it that this control does not call the SelectedIndexChanged Event upon selecting a new item?
 
ChrisSigh | :sigh:
QuestionDesigner Help Need ?memberreturnofjedi20 Dec '05 - 22:42 
hi Luke, Firstly thanks for this article that lead me to create my component although i am new to this.
 
your code is very complex for many purpose, but i need only one component. i copy most of part from your code, but i need help. I created designer interface for my control. when i open dialog prom preperties window and add colums it is ok till here. but when i close dialog it does not create reqired tags to html. even , i wrote folloving html tags by my hand it takes arguments to my control. but when i open property dialog dialog get properties that i wrote by my hand. again same thing when i close dialog it deletes what i wrote
 

<cc1:Repeater id="Repeater1" runat="server">
     <Columns>
          <cc1:Column ColumnName="Col1"></cc1:Column>
          <cc1:Column ColumnName="Col2"></cc1:Column>
          <cc1:Column ColumnName="Col3"></cc1:Column>
     </Columns>
</cc1:Repeater>
 
thanks in advance any idea, help or leeding
Note:I can send my code if required
 
-- modified at 5:03 Wednesday 21st December, 2005
GeneralValidationmemberjaredutley1 Nov '05 - 6:07 
This is an excellent collection of list items with a very useful set of increased functionality. One thing I would add:
 
As the controls are supplied, there is no defined ValidationPropertyAttribute for, say, the RadioButtonList. When adding validators to a form, the control will not show up in the ControlToValidate list. This can easily be fixed by adding a ValidationPropertyAttribute tag to the class declaration, such as:
 
[ValidationPropertyAttribute("SelectedValue")]
 
This will allow the control to be validated against.
More info: http://msdn2.microsoft.com/en-us/library/system.web.ui.validationpropertyattribute[^]
 
Jared Utley
GeneralRe: ValidationmemberLuke Foust1 Nov '05 - 6:13 
Thank you Jared. I just learned something new. I will add that and reupload.
 
If it weren't for my horse, I wouldn't have spent that year in college.
GeneralConvert to VB.NETmemberKirk Quinbar10 Oct '05 - 8:28 
anyone have a control like this one in VB.NET or convert this one to VB.NET? I started to, but realized that its a pretty big job even with a conversion utility and wanted to save myself some time someone else had already done it.
 

 
-- modified at 14:28 Monday 10th October, 2005
GeneralStyle AttributessussDejan Petrovic9 Aug '05 - 16:07 
Hi Luke, first let me congratulate you on this great article you have submitted.
 
The part that I was most interested in was the ListItem extension - RichListItem. Reason for that was my (so far unsuccessfull) atempt to write HTML, image enabled combo box. Most of the articles that I have seen so far, failed to go beyond fore-color and back-color style attributes. In fact, your RichDropdownList correctly displays colors, but fails with the font attributes (bold and italic are not displayed). Same thing happened with some other samples I have studied. Some style attributes were accepted, others were not. Is this the ListItem limitation, or something missing in this kind of approach?
 
Kind regards,
 

 
Dejan Petrovic
GeneralRe: Style AttributesmemberLuke Foust10 Aug '05 - 6:41 
Dejan,
Thanks for the kind words. I believe the limitations you are running into have more to do with html drop down lists than with my implimentation. As far as I know, most browsers do not support font attributes (except for maybe size). You can test this by looking at the html source of the Rich List Control. It outputs the correct styles for font attributes but it is ignored by the browser. Double check me on this and let me know what you find.
 
Thanks,
Luke
 
If it weren't for my horse, I wouldn't have spent that year in college.
GeneralRe: Style AttributesmemberDejan Petrovic10 Aug '05 - 18:24 
Hi Luke,
 
Yes, you are right. All font-related style attributes are rendered correctly in the source, but they are still not being displayed in the browser (IE).
This leaves me with no option other than starting image combo box from the scratch.
Thanks for the clarification on the matter,

GeneralView State Errormembermichael80548 Jun '05 - 13:29 
Thanks for your great article, it has been a huge help to me.
 
I have however incounted a problem when dynamically add items to a one of your rich list controls. One item can be add to a list dynamically but when the next postback occurs i get the following Error-
 
Exception Details:
System.Web.HttpException (0x80004005): Failed to load viewstate. The control tree into which viewstate is being loaded must match the control tree that was used to save viewstate during the previous request. For example, when adding controls dynamically, the controls added during a post-back must match the type and position of the controls added during the initial request.
 
Stack Trace:
System.Web.UI.Control.LoadViewStateRecursive(Object savedState) +187
System.Web.UI.Control.LoadViewStateRecursive(Object savedState) +410
System.Web.UI.Control.LoadViewStateRecursive(Object savedState) +410
System.Web.UI.Page.LoadPageViewState() +306
System.Web.UI.Page.ProcessRequestMain() +423
 
if any one knows how i can over come this problem could you please let me know.
 
Thanks
 

 

 

 
ddd
GeneralRe: View State Errormemberbeinhoff16 Mar '06 - 23:32 
Hi,
Using the RichListControls is giving me the same Error as you.
Here´s my code:
 
for (int i=0; i< dataSet1.Tables["spSprakVal"].Rows.Count -1; i++ ){
richItem = new RichListControls.RichListItem();
richItem.Text=dataSet1.Tables["spSprakVal"].Rows[i]["fldrubrik"].ToString();
richItem.Value=dataSet1.Tables["spSprakVal"].Rows[i]["fldid"].ToString();
richItem.ToolTip=dataSet1.Tables["spSprakVal"].Rows[i]
["fldtooltip"].ToString();
richListBoxList1.Items.Add(richItem);
}
 
Have you found a solution?

 
//Anders Beinhoff
GeneralRe: TooltipmemberLuke Foust19 Nov '04 - 7:33 
Can you give more details on the Tooltip not working? It seems to work fine for all my tests so any code you can provide would be helpful.
 
If it weren't for my horse, I wouldn't have spent that year in college.
GeneralRe: TooltipmemberThea Burger21 Nov '04 - 22:54 
I created a new project and referenced your RichListControls.dll. I also added the controls to the toolbox. Then dragged a RichCheckboxList and a RichRadiobuttonList onto my form. Here is the HTML (no extra code in code-behind):
 
<%@ Page language="c#" Codebehind="CheckBoxList2.aspx.cs" AutoEventWireup="false" Inherits="Checkboxlist.CheckBoxList2" %>
<%@ Register TagPrefix="cc1" Namespace="RichListControls" Assembly="RichListControls" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
<HEAD>
<title>CheckBoxList2</title>
<meta name="GENERATOR" Content="Microsoft Visual Studio .NET 7.1">
<meta name="CODE_LANGUAGE" Content="C#">
<meta name="vs_defaultClientScript" content="JavaScript">
<meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5">
</HEAD>
<body>
<form id="Form1" method="post" runat="server">

<cc1:RichRadioButtonList id="RichRadioButtonList1" runat="server">

Zero
One
Two

<cc1:RichCheckBoxList id="RichCheckBoxList1" runat="server">

BMW
Volkswagen
Mercedes

</form>
</body>
</HTML>

 
When I run it, the RichRadioButtonList's tooltip works perfectly, but not the RichCheckboxList tooltips Frown | :(
 
Thanks for looking at it!!!
Thea

GeneralRe: TooltipmemberThea Burger21 Nov '04 - 23:09 
Oops!! Code between the form tags:
 
<P>
                    <cc1:RichRadioButtonList id="RichRadioButtonList1" runat="server">
                         <Items>
                              <cc1:RichListItem ToolTip="Zero" Style-BackColor="#FFC0C0" Value="Zero">Zero</cc1:RichListItem>
                              <cc1:RichListItem ToolTip="One" Style-BackColor="#C0FFC0" Value="One">One</cc1:RichListItem>
                              <cc1:RichListItem ToolTip="Two" Style-BackColor="#FFFFC0" Value="Two">Two</cc1:RichListItem>
                         </Items>
                    </cc1:RichRadioButtonList></P>
               <P>
                    <cc1:RichCheckBoxList id="RichCheckBoxList1" runat="server">
                         <Items>
                              <cc1:RichListItem ToolTip="BMW" Style-ForeColor="White" Style-BackColor="#404040" Value="BMW">BMW</cc1:RichListItem>
                              <cc1:RichListItem ToolTip="Volkswagen" Style-BackColor="#FF8080" Value="Volkswagen">Volkswagen</cc1:RichListItem>
                              <cc1:RichListItem ToolTip="Mercedes" Style-BackColor="#C0C0FF" Value="Mercedes">Mercedes</cc1:RichListItem>
                         </Items>
                    </cc1:RichCheckBoxList></P>
GeneralRe: TooltipmemberLuke Foust22 Nov '04 - 5:20 
I found the problem. There was a bug in the Check Box List that did not set the ToolTip correctly. Thanks for your help in finding this bug. I have re-submitted the source to TheCodeProject but if you need it sooner than they post it, just email me.
Thanks,
Luke
 
If it weren't for my horse, I wouldn't have spent that year in college.
GeneralRe: TooltipmemberChris Kish8 Dec '04 - 10:57 
I was wondering if the same issue occurs in the dropdown list tooltip, and if you fixed it. We have the sample project and the tooltip is not appearing . . . Any help would be, well, helpful!
 
Thanks,
Chris
GeneralRe: TooltipmemberLuke Foust8 Dec '04 - 11:05 
Correct me if I am wrong, but I don't think that Drop Down Lists (or Drop Down List Items) can have Tooltips in HTML. There are some things that apply to RadioButton Items and Check Boxes that don't really tranlate over to drop down lists.
 
If it weren't for my horse, I wouldn't have spent that year in college.
GeneralRe: TooltipmemberChris Kish8 Dec '04 - 12:57 
I'm quite sure you're right - we were looking for this feature when we happened across your cool project.   We're thinking of doing something with GetClientRectangles and the onMouseMove event to obtain the text of an <option> that the mouse is over.   Not sure if we can do it yet - but if we can, we were thinking of putting that text somewhere to simulate a tooltip.   If we get around to doing it, I'll let you know what we come up with.
 
Best regards,
Chris
GeneralTooltipmemberThea Burger17 Nov '04 - 23:37 
This is real cool, but I can't seem to get the Tooltip working.
I have tried your solution and created my own solution and referenced the RichListControls.dll, but nothing. Confused | :confused:
Is there something that I missed?
The style is working perfectly.
 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web04 | 2.6.130523.1 | Last Updated 1 Nov 2005
Article Copyright 2004 by Luke Foust
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid