![Image 1](/KB/list/HtmlDropDownList/HtmlDropDownList.jpg)
Introduction
The HtmlDropDownList
control is a Windows Forms control extending the ComboBox
, it uses owner drawing to display a limited set of HTML and raises an event when an anchor link is clicked.
Background
I recently had an application that required the user to select a search criteria where each criteria had some additional parameters. The screen was already cramped with a docked TreeView
and two docked ListView
controls. I wanted the user to be able to select a criteria and then click on a 'hyperlink' that would display another dialog to allow them to enter additional parameters.
So, if they select a criteria like file size:
![Image 2](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Then clicked on the size link they would be presented with a File Size Selection Criteria dialog:
![Image 3](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
They could then enter the criteria and the HtmlDropDownList
SelectedItem
would be updated to reflect the values.
![Image 4](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
This also made it easy for me to add options later, without redesigning the UI and I could dynamically limit options depending on who the user was.
Using the code
The bulk of the HtmlDropDownList
source code is contained in the file, HtmlDropDownList.cs, there are three private
nested classes within this file for parsing the HTML and for the LinkClicked
event arguments. There are four enum
s defined in the files BrushType.cs, ElementType.cs, TagAttribute.cs and WriteMethod.cs. The rest of the files within the project are part of the custom editor for the design time support of the Items
collection.
The HtmlDropDownList
displays a drop-down list style ComboBox
, where the text portion is not editable. A standard drop-down list style ComboBox
will display the list box portion if the text portion of the control is clicked. This was no good for me as I wanted to respond to a click on a hyperlink. This meant the control has to handle the WM_LBUTTONDOWN
Windows message and only show the list portion if the click was on the drop-down arrow.
The HTML used must conform to the stricter XML rules (i.e. be well-formed HTML). Exceptions to the XML rules are; there is no need for a single root tag as one is generated by the control and the tags and attributes are not case sensitive. The XML rules that do apply are; all tags must be closed, this relates mainly to the <IMG>
tag, no tags can overlap, (i.e. <B>Bold <I>Bold and Italic</B> Italic</I> is invalid) and all attributes must be surrounded by single or double quotation marks.
The level of support for HTML is very limited as I started off just wanting to handle the <A>
tag. However, as with most of my home projects I did add more functionality where my interest took me. This was the first time I was using the GDI+ based class, so I added a BRUSH tag to play with some more effects.
Tag | Description |
---|
A | Anchor: Supported attribute: id .
The id attribute value is used to identify the link in the LinkClicked event and the methods ReplaceInnerText and ReplaceInnerHtml .
<a id="size">size</a>
|
B | Bold font.
<b>text</b>
|
BRUSH | Brush: Supported attributes: type , shadowcolor , startingcolor , endingcolor , gradientangle , offset .
The values for the type attribute can be "LinearGradient " or "Shadow ".
For a "LinearGradient " brush the attribute startingcolor represents the starting color for the gradient, endingcolor represents the ending color for the gradient and gradientangle represents the gradient's orientation line angle.
This example shows a linear gradient brush from Red to Blue from left to right.
<brush type="LinearGradient" StartingColor="Red"
EndingColor="Blue" GradientAngle="0"></brush>
For a "Shadow " brush the attribute offset represents the size of the shadow and shadowcolor the color of the shadow.
This example shows a Shadow brush with an offset of two pixels and a shadow color of Blue.
<brush type="Shadow" offset="2" shadowcolor="Blue"></brush>
Note: This is not a standard HTML tag.
|
FONT | Font: Supported attributes: color , font .
This example shows the color attribute specifying known named color.
<font color="blue"/></font>
This example shows the color attribute specifying an RGB value.
<font color="#800080"/></font>
Note: The RGB value must be six hexadecimal digits.
The font attribute value is the string representation of the FontFamily object for the new Font object as used in the Font constructor. Invalid values we be ignored and the controls Font property will be used. This example shows the face attribute specifying a "Courier New" font.
<font face="courier new"/></font>
|
I | Italic font.
<i>text</i>
|
IMG | Image: Supported attributes: src .
The src attribute can specify a filename or index into the control's ImageList .
This example shows the src attribute specifying a filename.
<img src="images/blue.bmp"/>
This example shows the src attribute specifying an index into the ImageList .
<img src="#1"/>
|
S | Strikeout.
<s>text</s>
|
U | Underline.
<u>text</u>
|
The color
attribute values can specify a GDI+ color name or an RGB value. Invalid values we be ignored and the control's ForeColor
property will be used.
Note: The GDI+ known colors are recognized by IsKnownColor
and are the same as the HTML color names. The GDI+ system colors are recognized by IsSystemColor
and are different from the HTML color names. For example you need to use the GDI+ ActiveCaptionText
value not the HTML CaptionText
.
The only HTML character entity references (e.g. , © and ® ) that are handled correctly are &, ", ', <, and > for the characters &, ", ', <, and > respectively as these are automatically handled by the XmlTextReader
class. Numeric character entity references are also supported by XmlTextReader
so € will display the euro currency symbol, €.
The event LinkClicked
is raised when a link is clicked. The LinkClicked
event includes the HtmlDropDownList.LinkClickedEventArgs
that defines the link id
, InnerText
and InnerHtml
of the link. The methods ReplaceInnerText
and ReplaceInnerHtml
allow the InnerText
and InnerHtml
, respectively to be updated. The properties BaseHref
allows the base path for images to be specified. An ImageList
has been added to allow images to be specified by the index. The LinkColor
allows the default color of the text marking links to be specified. The SelectedIndex
allows the selected item to be selected at design time.
If the text to be displayed involves different styles of font (e.g. Italic, Bold, ...) then extra space may appear between the different pieces of text. This will be especially noticeable at smaller font sizes as the effects of font scaling and grid fitting become more noticeable. The default rendering is grid-fitted if the text spacing is not accurate enough you can specify a value AntiAlias
in the TextRenderingHint
property. This will avoid grid fitting and correct the spacing but can make the text appear greyish.
Note: The default rendering on Windows XP can be changed under the Display Properties, Appearance tab click the Effects... button then select an option from the "Use the following method to smooth edges of screen fonts:" drop down list.
There is some design time support for the control. The BaseHref
uses the System.Windows.Forms.Design.FolderNameEditor
to display the "Browse for Folder" dialog. The Items
collection has a custom editor that may one day be an HTML editor but at the moment is not so grand but does allow you to see what will be displayed at design time. But you can select text and make it bold (for example) by clicking the Bold button on the toolbar.
One thing I learnt doing the editor and using the ComboBox
with a DropDownStyle
of ComboBoxStyle.Simple
, as used in the HtmlDropDownList
Items Editor, is that you don't get to do owner drawing of the Text portion of the control. However I think I can sell this as a feature as it means I get to see the HTML in the Text portion and the rendered HTML in the List portion.
![Image 5](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Points of interest
My motivation for submitting this code is to generate some feedback, on the control and also how I've coded it. I've learnt a lot from seeing other people's code but am constantly reminded how much more there is to learn.
There's no code in this article but I like to think the code is well documented and easy to follow.
Once you have downloaded the source you will need to rebuild the solution before you can access the HtmlDropDownList Items Editor at design time. If you don't, you will get an "Invalid Cast" message.
To access the HtmlDropDownList Items Editor, select an HtmlDropDownList
control in the designer, select the Items
property and then click on the "..." button. Instead of getting the String Collection Editor you would with a ComboBox get the HtmlDropDownList Items Editor.
History
- July 9th, 2005: Initial version.
- Delivery day + 1: Changed the demo program by adding a
DoEvents
when populating the Items with Fonts after each fifth one. - Delivery day + 10: Numerous improvements to the demo program and the HtmlDropDownList Items Editor.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.