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

VB.NET Windows Forms ListBox Extension: TemplateListBox

, 4 Jul 2006
Rate this:
Please Sign up or sign in to vote.
A class that extends the ListBox control by adding collapsable items and providing a simple way to add multiple controls into a ListBox item.

Introduction

First of all, I must say that English is not my native language, so be indulgent with my text. The TemplateListBox class inherits the ListBox class, and thus behaves mainly in the same way. The TemplateListBox extends the ListBox control by adding collapsible items, and providing a simple way to add multiples controls (or rather a simulation of controls) into a ListBox item. In the template item of a TemplateListBox, you can put controls to display them at any position you want, and do it at design time as if you put them in a UserControl.

Disclaimer: This code is provided "As Is"; I will not take responsibility for any problems caused due to its use.

Background

In Web Forms world, we have a control named Repeater, but in the Windows Forms world, that kind of a control doesn't exist. With the TemplateListBox, you will be able to have a Repeater control in the Windows Forms World.

My first try was to use a Panel control with UserControls in it, but that kind of an approach is too heavy in memory usage, and too much slow when we have many items to display; so I tried the CheckedListBox approach, i.e., drawing controls rather than creating real ones. I also use Reflection to simulate the behaviors of real controls.

Using the code

To use the TemplateListBox control, you must work with two classes:

  • TemplateListBox
  • TemplateItem

You can do this in four steps.

  1. Create a new TemplateListBox on your form.
  2. Set the TemplateItemName and DataSource properties of the TemplateListBox control in the Form_Load event of the Form like in the sample below. Note that the CreateDataSource method in this sample returns a DataView object.
    Private Sub Form1_Load(ByVal sender As Object, _
            ByVal e As System.EventArgs) Handles MyBase.Load
        TemplateListBox1.TemplateItemName = "UserControl1"
        TemplateListBox1.DataSource = CreateDataSource()
  3. Create the template item. One way to do this is to add a new UserControl in your project (use the same name of the TemplateItemName property value from step 2) and replace the heritage from the UserControl class with the TemplateItem class. After that, place the controls you want on the template item like in the Figure 1 (note that I have only tested LinkLabel, Label, Button, and CheckBox controls).

    In the UserControl, you will see a delimiter line which separates the heading from the detail section (the height of the heading can be modified with the HeadingHeight property). Note that the heading will be the only visible part when the item of the TemplateListBox collapses.

    Figure 1

  4. Set the bindings for each control you want to in the UserControl constructor (New) using the DataBindingItemList collection like in the sample below. In the sample, LinkLabel1 is the control, Text is its property to bind, and StringValue is the data field name from the DataSource (in my example, the DataSource is a DataView).
    Public Sub New()
        MyBase.New()
    
        'Cet appel est requis par le Concepteur Windows Form.
        InitializeComponent()
    
        'Ajoutez une initialisation quelconque après l'appel
        InitializeComponent()
        Me.DataBindingItemList.Add(LinkLabel1, "Text", "StringValue")
    End Sub

More features

Let's see more features by analyzing the other sample code lines below.

With the TooltipCtrl property, you can set the Tooltip control that will be used in the TemplateListBox, for each control that you want to set a tooltip text in the template item (I'll show you a sample in the next section).

The SetItemExpandable method allows a TemplateListBox item to be expandable or not. The default behavior can be set with the ItemExpandable property.

Before the TemplateListBox is shown, you can expand or collapse an item with the SetItemExpanded. The default behavior can be set with the ItemExpanded property.

Private Sub Form1_Load(ByVal sender As Object, _
        ByVal e As System.EventArgs) Handles MyBase.Load
    TemplateListBox1.TemplateItemName = "UserControl1"
    TemplateListBox1.DataSource = CreateDataSource()
    TemplateListBox1.TootipCtrl = ToolTip1

    TemplateListBox1.SetItemExpandable(0, False)

    TemplateListBox1.SetItemExpanded(1, True)
    TemplateListBox1.SetItemExpanded(3, True)
End Sub

If you want more custom initializations, you can use the CustomDataInitialization event. Note that the BindingMode property value of the TemplateListBox must be Custom or AutoAndCustom for this event to be triggered. This event is triggered each time a TemplateListBox item must be drawn.

If you have set the TemplateListBox TooltipCtrl property, you can set the tooltip text for each control you want, by using the SetControlTooltipText method, and for performance, you can also use the SetControlStaticTooltipText method if your tooltip text never changes for each TemplateListBox item.

To set a control invisible or disabled, you must use SetControlVisible and SetControlEnabled, respectively.

Private Sub UserControl1_CustomDataInitialization(ByVal e As _
        WindowsControlLibrary7.CustomDataInitializationEventArgs) _
        Handles MyBase.CustomDataInitialization
    'LinkLabel1.Text = "Toto" & e.DataItem(1).ToString
    SetControlTooltipText(e.ListItemIndex, LinkLabel1, _
                          "Tooltip" & e.DataItem(1).ToString)
    SetControlStaticTooltipText(Button1, "This is always the same text !")
    SetControlStaticTooltipText(Label1, "This is always the same text !")

    If e.ListItemIndex Mod 2 = 0 Then
        SetControlVisible(e.ListItemIndex, Label1, True)
    Else
        SetControlVisible(e.ListItemIndex, Label1, False)
    End If

    If e.ListItemIndex = 3 Then
        SetControlEnabled(e.ListItemIndex, Button1, False)
    End If
End Sub

Note that, for now, my control supports only two events: LinkClicked event for the LinkLabel control and all controls that inherits the LinkLabel class, and the Click event for all other controls (you can see a sample from the UserControl of the two events in the code below).

Private Sub Button1_Click(ByVal sender As System.Object, _
                          ByVal e As System.EventArgs)
    MsgBox("Button1 of Item" & Me.TemplateListBoxParent.SelectedIndex)
End Sub

Private Sub LinkLabel1_LinkClicked(ByVal sender As System.Object, _
            ByVal e As System.Windows.Forms.LinkLabelLinkClickedEventArgs)
    MsgBox("LinkLabel1 of Item" & Me.TemplateListBoxParent.SelectedIndex)
End Sub

To see all the features of the TemplateListBox, check the class diagram (figure 2).

Class diagram

The class diagram shows the classes with their public properties, methods, and events:

Figure 2

Points of Interest

At the beginning of the development of this control, to draw each control, I used a distinct method for each one. The problem with that solution is that we are limited to the controls we know. For example, that solution will not work with a custom control which has implemented its own Paint method. So, I replaced all those functions by only one (PaintControl), which makes it possible to copy the appearance of a control in an image object and then drawing it in the TemplateListBox items. Thanks to reflection that makes all this possible. By the way, I also used reflection to simulate the behavior of all controls in the items of a TemplateListBox control.

History

  • Version 1.0.0.0.

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

Share

About the Author

J.P.B.
Web Developer
Canada Canada
No Biography provided

Comments and Discussions

 
GeneralMy vote of 5 Pinmembermanoj kumar choubey12-Mar-12 21:50 
Questioncheckbox1 question Pinmembermichael_liumeng16-Jul-09 4:13 
GeneralThe executable fails to launch Pinmemberkhalidco26-Aug-06 10:49 
GeneralRe: The executable fails to launch PinmemberJ.P.B.28-Aug-06 7:11 
GeneralRe: The executable fails to launch Pinmemberkhalidco29-Aug-06 8:42 
GeneralRe: The executable fails to launch PinmemberJ.P.B.29-Aug-06 13:13 
GeneralFantastic work ! PinmemberGluteous Maximus22-Aug-06 11:23 
GeneralRe: Fantastic work ! PinmemberHojjat Salmasian26-Aug-06 1:57 
GeneralRe: Fantastic work ! PinmemberJ.P.B.28-Aug-06 6:56 
QuestionConversion to VB.Net 2005 Pinmemberarbeamer22-Aug-06 9:30 
AnswerRe: Conversion to VB.Net 2005 PinmemberJ.P.B.28-Aug-06 6:38 
QuestionHow to make expand/collaps work with VS .NET 2005 PinmemberJ.P.B.9-Aug-06 16:36 
QuestionSupport of other controls? Pinmemberanomaly26-Jul-06 5:42 
AnswerRe: Support of other controls? PinmemberJ.P.B.9-Aug-06 16:47 
GeneralRe: Support of other controls? PinmemberJ.P.B.9-Aug-06 17:02 
GeneralRe: Support of other controls? PinmemberJ.P.B.28-Aug-06 18:40 

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

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web02 | 2.8.140827.1 | Last Updated 4 Jul 2006
Article Copyright 2006 by J.P.B.
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid