ExtComboBox inherit from the
ComboBox controls, respectively--and have the following extra features:
- Allows one to specify images to display before (or in place of) text for individual list items, as well as the ability to set the fonts and colors of the text of individual items
- Allows one to have multi-line text for a given list item (simply embed carriage-return/line-feed sequences in the item's text)
- Allows one to intelligently line up columns of list items (
ExtListBox only) with one command
Using the Code
ExtListBox and ExtComboBox Controls
These inherit from
ComboBox, respectively--and have the following custom features:
DrawMode -- Specifies where one is to have a fixed or variable vertical item-height, based on
ExtListAndCombo.DrawMode enumeration value. (The control is always configured as "owner-draw" to allow graphic manipulation--although the
MeasureItem events are suppressed, since the control does its own custom imaging. If you attempt to set
DrawMode.Normal, an exception is thrown.)
DisplayMode -- Specifies whether to display text only, images only, or both (image to left, text to right) based on
ExtListAndCombo.DisplayMode enumeration value.
ImagePadding -- Determine dimensions (
Padding of images displayed; defaults to a square image with 1 pixel of padding all round, sized using initial
Image to display when none is specified for a list-item; defaults to no image.
SelectedItemInfo -- Gets or sets full information (including image/font/color) about the selected list item, as an
Custom Members of Auxiliary Classes
An instance of this class contains the object, and the graphical information associated with it, of a list item or potential list item. Its members are as follows:
Value -- Property for
Object of list item
Image -- Property for
Image to be assigned to list item. If
Nothing, then the value of the underlying control's
DefaultImage property (or no image if that property is also
Nothing) will be assigned by default when the item is assigned or added to the list.
Font -- Property for
Font to use when displaying item text; defaults to the control's
Color -- Property for foreground
Color that item text displays item in when not highlighted; defaults to control's
ToString -- Method for item's text; always the same as
ExtListBox.ObjectCollection and ExtComboBox.ObjectCollection Classes (Items Property)
These inherit from
ComboBox.ObjectCollection, respectively. The principal custom functionality is as follows:
Item(index) gets or sets the underlying
Object corresponding to a list item;
ItemInfo(index) gets or sets a list item's full graphical information, as specified by an
ItemInfo instance. (
ItemInfo(index).Value = Item(index).)
Insert feature overloads that allow one to optionally specify image, font, and/or color for an object; each also has an overload that takes an
ItemInfo instance specifying the list item and its graphical information as a single parameter.
AddRange features overloads that take an
Object() array or a base-class
ObjectCollection instance with optional (common) image/font/color as parameters. It also has overloads that take an
ItemInfo() array or a derived-class
ObjectCollection as the sole parameter; the latter is useful when each list item has different graphical information.
CopyTo copies either the main object (value) to an
Object() array, or the full information (including image, font, and color) to an
ItemInfo() array, depending on the type of array specified.
ExtListBox.IntegerCollection class (CustomTabOffsets property)
This inherits from
ListBox.IntegerCollection; its custom features are as follows:
Item(index) values for tab offsets are specified in pixels, rather than dialog units; the offsets are relative to the beginning of the text portion of a list entry.
AddRange allows one to specify an
Integer() array, an existing (derived-class)
IntegerCollection, or a base-class
IntegerCollection, as its parameter. (In the latter case, dialog units are converted, using the control's overall
Font, into pixels.)
AlignTabs method is provided which measures all of the columns in the list items and creates/expands tab offsets so that all corresponding columns line up horizontally. It also sets the
HorizontalExtent property of the control in case a
HorizontalScrollbar is enabled. It takes an optional
Integer parameter (defaults to
1) to specify minimum pixels of white-space between columns. (Even if no list items use tabs, this method is useful when using a horizontal scroll bar, because it sets the
HorizontalExtent property to the longest item;--be sure to enable
Unlike the standard
ExtListBox does not use "default tabs" if custom tabs are not specified. If
False, or if no tab offsets are created, then any tab characters in the text are left unexpanded.
ExtListBox.SelectedIndexCollection class (SelectedIndices property)
This inherits from
ExtListBox.SelectedObjectCollection class (SelectedItems property)
This inherits from
ListBox.SelectedObjectCollection, and has the following custom functionality:
ItemInfo(index), which gets or sets the full information about a list item as an
CopyTo copies list into array--
Object() for main object or
ItemInfo() for full information.
- Since I have been unable to ensure that the
DataSource property stores the full information (image, font, and color along with object values) about items from a data source, this property is "disabled". It is shadowed as read-only and returns
Nothing;--as a result, the
ValueMember properties, which themselves have trouble accessing "nested" properties (i.e., "
Value.displayorvalueproperty") anyway, are not particularly useful either. (Sorry about that, and if anyone can fix this, I'm interested.) You can instead load your data into an array or
ObjectCollection and add then use
AddRange to add it manually. (This technique affords you more control, particularly over the graphical information, anyway.)
- Because of the way that each control's
ObjectCollection is extended, the
Items property--and, for the
ExtListBox control, the
SelectedItems properties--are not accessible (browsable) at design time. You must fill the list (and make any pre-selections) at run-time!
- If you use "
For Each variable ..." to enumerate the
Items property) or
SelectedItems property), each
variable will be of type
ItemInfo, with the full information about the entry. Use
variable.Value to access the underlying
Dim ItemInfo As ItemInfo = New ItemInfo("Multi-line" & ControlChar.CrLf & "text", _
ImageList1.Images.Item(0), New Font("Arial"), Color.Red)
ExtListBox1.Items.Add(Value, Image, Font, Color)
ExtListBox1.Items.Add("Column 1, Row 1" & vbTab & "Column two, Row two" & vbCrLf _
& "Column one, Row two" & vbTab & "Column 2, Row 2")
ExtComboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList
ExtComboBox1.DrawMode = ExtListAndCombo.UseVariableHeight
ExtComboBox1.DisplayMode = ExtListAndCombo.DisplayMode.ShowImageAndText
ExtComboBox1.DefaultImage = ImageList1.Item(2)
ExtComboBox1.ItemInfo(Index) = ItemInfo
ExtComboBox1.DroppedDown = True
Points of Interest
In order to ensure that the items in the list and their respective graphical information are kept synchronized whenever changes are made to the list, the full information is stuffed into an
ItemInfo instance, which is what
MyBase.Item of the
ObjectCollection sees. Also, this project relies heavily on inheriting, overriding, and (particularly) shadowing pre-existing members in order to splice in the custom functionality.
It should be noted that while the end user sees and uses the collections of the derived classes for these controls, the CLR sees and uses the collections of their base classes. As a result, the respective (derived- and base-control) collections have to be synchronized in order for the "behind the scenes" stuff to function properly. To facilitate this, the
ExtListBox only), and
ExtListBox only) feature an "infrastructure" property (exposed only to the
ExtComboBox controls, not external projects) --
BaseCollection, which are set to
FindStringExact methods of the controls are shadowed in order to fix a known bug in the base-class controls, which causes exceptions to be thrown when the start index is equal to the last item. The derived-class versions use an index of
-1 (beginning of list) whenever the specified index is the last item, thus avoiding the exception.
P.P.S. This version has been updated to fix a bug involving the
SelectedItem properties whenever multi-selection is allowed (see above for more).