May 10, 2006 12:05 AM

Hot Menu Options

Make Your Sites Sizzle with a Custom HoverList Control
DevConnections
Rating: (0)

ControlFreak

LANGUAGES:VB.NET | C#

ASP.NETVERSIONS: 2.x

 

Hot Menu Options

Make Your Sites Sizzle with a Custom HoverList Control

 

 

You can never have too many menu controls. Ever. But moreis not always good enough ? they have to be unique, as well. A unique menucontrol can really differentiate a Web site, making it stand out from theinformation overload that is the World Wide Web. To help you get moving in thisdistinctive direction, try using the HoverList custom control provided with thisarticle to spice up your site.

 

The HoverList control contains configurable menu itemsthat highlight as the mouse is moved over them at run time. The list can bespecified at design time or run time, and may optionally be data bound. Eachlist item consists of a string value and a formatted text item that mayoptionally include HTML. A configurable header area is also optionally included(see Figure 1).

 


Figure 1: The HoverList controlcontains a configurable list of menu items that can be highlighted with variouscolor effects as the mouse hovers over them.

 

To use this control, download the sample code and add theincluded HoverList.dll to your Visual Studio 2005 toolbox (see end of articlefor download details). Then drag it onto any WebForm to get started using it. TheASPX declaration looks roughly like this (depending on how the control?sproperties have been configured):

 

<cc1:hoverlist id="HoverList1"runat="server"

 borderstyle="Solid" borderwidth="1px"

 datasourceid="SiteMapDataSource1"

 datatextfield="Title"datavaluefield="Url"

 hoverbackcolor="Blue" hoverforecolor="LightCyan"

 padding="0.2em"width="200px">

</cc1:hoverlist>

 

The design-time experience is very much like working witha ListBox because the ListBox and the HoverList control both inherit fromListControl (as explained in more detail later). The HoverList?s mostnoteworthy members are listed in the table in Figure 2. There are severalproperties for configuring the appearance of the header area of the control,and a couple important properties for configuring the color changes that happenwhen the mouse is hovered over each menu item.

 

Noteworthy HoverList Members

Description

OnSelectedIndexChanged event

Raised whenever the user clicks on one of the menu items.

ShowHeader property

Specifies the visibility of the header area. Default: True

HeaderText property

Specifies the text displayed in the header area.

HeaderBackColor property

Specifies the background color of the header area. Default: LightBlue

HeaderForeColor property

Specifies the color of the header text. Default: Black

HeaderFont property

Specifies the font of the header text.

HoverBackColor property

Specifies the background color of the menu when the mouse hovers over it. Default: Blue

HoverForeColor property

Specifies the text color of the menu item when the mouse hovers over it. Default: LightCyan

Padding property

Specifies the padding around the edge of the control. Default: 0.2em

HorizontalAlign property

Specifies the alignment of the menu items. Default: Center

AppendDataBoundItems property

Appends data-bound items to statically declared list items. Default: False

Figure 2: TheHoverList control provides several useful members in addition to those that thebase ListControl already provides.

 

The HoverList control?s menu items can be configured atdesign time via the standard ListItem Collection Editor shown in Figure 3. Alternatively,items can be added programmatically at run time or standard data-bindingtechniques can be applied. You can even combine these techniques, thanks to theAppendDataBoundItems property.

 


Figure 3: The HoverList controlsupports standard data-binding techniques, or items can be added at design timethrough the ListItem Collection Editor dialog box.

 

AppendDataBoundItems is a new property of the baseListControl class (as of ASP.NET version 2.0). It lets you declare one or morelist items at design time, and then also add data-bound list items at run time.This is especially useful for controls such as DropDownList, because you canconfigure the first item to say ?Choose an item from the list? and then add therest of the list via standard data binding. This was not possible in ASP.NET 1;instead, you either needed to ditch data binding or add a dummy record to thedata source to achieve such functionality.

 

When the user clicks on one of the HoverList?s menu itemsat run time, the page posts back and the OnSelectedIndexChanged event israised, as demonstrated here:

 

Protected Sub HoverList1_SelectedIndexChanged(ByVal _

 sender As Object, ByVal eAs System.EventArgs) _

 HandlesHoverList1.SelectedIndexChanged

 

 Response.Write("YouClicked: " & HoverList1.SelectedValue)

End Sub

 

That covers most of what you need to know to use theHoverList control. If you?re the intellectually curious type (which I assumemost of you are), keep reading to tour the source code and find out about thedetails of its inner workings.

 

Viscera

One of the most fundamental pieces of information aboutthe HoverList control is that it inherits from ListControl. ListControl is anabstract base class provided by the .NET Framework from which many commoncontrols inherit. A few of the standard ASP.NET controls that extend theListControl class are ListBox, DropDownList, and CheckBoxList. Like thesecontrols, HoverList doesn?t need to deal with trivia, such as data binding,because that is all handled by the base ListControl class. This greatlysimplifies the code, reducing it to little more than an exercise in HTMLrendering. Essentially, the HoverList control consumes the collection ofListItems that is managed by the ListControl class, and renders custom HTMLfrom that data. The general structure of the control is shown here:

 

<DefaultProperty("HeaderText"), _

ToolboxData("<{0}:HovrList runat=server></{0}:HovrList>")>_

Public Class HoverList

   Inherits ListControl

   ImplementsIPostBackEventHandler

 

      'TODO: constructor

 

      'TODO: publicproperties

 

      'TODO: Rendering

 

      'TODO: Postbackhandling

 

End Class

 

Another important detail is that the control implementsthe IPostBackHandler interface. This enables the control to handle postbacks ina standard way. The associated code is located in the RaisePostBackEventroutine. The logic is simple for the HoverList control: Unselect any previouslyselected item and ensure that the item the user clicked is now the selecteditem. Then hand off control to the base class ? which will raise the standardOnSelectedIndexChanged event to the page:

 

Public Sub RaisePostBackEvent(ByVal _

   eventArgument AsString) Implements _

   System.Web.UI.IPostBackEventHandler.RaisePostBackEvent

 

   If SelectedItem IsNotNothing Then

       SelectedItem.Selected = False

   End If

   Dim li As ListItem = _

       Items.FindByValue(eventArgument)

   If li IsNot NothingThen li.Selected = True

   MyBase.OnSelectedIndexChanged(Nothing)

End Sub

 

You?ll notice references to the SelectedItem property andthe Items collection, but you?ll find no such properties in the HoverListsource code. Rather, these properties are inherently available from the baseListControl class. Therefore, the HoverList control only needs to define theunique properties it requires for its customizable rendering chores. While mostof the properties are utilitarian in nature, a couple of them are shown inFigure 4 to give you a taste.

 

<Bindable(True), Category("Appearance"), _

Description("Sets or gets the font color of theheader.")> _

Public Property HeaderForeColor() As System.Drawing.Color

 Get

   IfViewState("HeaderForeColor") IsNot Nothing Then

     ReturnCType(ViewState("HeaderForeColor"), Color)

   Else

     Return Color.Black'default

   End If

 End Get

 Set(ByVal value As Color)

   ViewState("HeaderForeColor") = value

 End Set

End Property

 

Private Const Content As _

System.ComponentModel.DesignerSerializationVisibility = _

DesignerSerializationVisibility.Content

 

Private _lblHeader As Label = New Label

 

<Bindable(True), Category("Appearance"), _

Description("The font applied to the header area."), _

NotifyParentProperty(True), _

DesignerSerializationVisibility(Content)> _

Public Property HeaderFont() As FontInfo

  Get

     IfViewState("HeaderFont") IsNot Nothing Then

         ReturnCType(ViewState("HeaderFont"), FontInfo)

     Else

         Return_lblHeader.Font

      End If

  End Get

  Set(ByVal value AsFontInfo)

     ViewState("HeaderFont") = value

  End Set

End Property

Figure 4: Becausethe concept of a header is foreign to the base ListControl class, the HoverListcontrol must explicitly define header-related properties.

 

The HeaderForeColor property is needed so the applicationdeveloper may specify which color they would like the text of the header areato be. The property stores the property in ViewState, and uses Black bydefault. The HeaderFont property is a little more complicated because of thefact that the Font property is complex and contains many sub-properties. Mostof the details related to this are managed by .NET automatically ? if you tellit to. That?s what the extra attributes are for ? NotifyParentProperty andDesignerSerializationVisibility are critical for ensuring the properties arepersisted properly, especially at design time.

 

Of course, all these properties are pointless until theyare used by the rendering code to output the customized HTML that makes up theHoverList control. The overridden Render event is listed in Figure 5.

 

Protected Overrides Sub Render(ByVal tw As HtmlTextWriter)

 

   'create a container

   Dim pnl As Panel =CreateContainer()

 

   'create the header

   If Me.ShowHeader ThenCreateHeader(pnl)

 

   'create each list item

   For Each li As ListItemIn Me.Items

       CreateItem(pnl, li)

   Next

 

   pnl.RenderControl(tw)

 

End Sub

Figure 5: Theoverridden Render event delegates rendering tasks to several other internalfunctions.

 

As you can see, each piece of the control is rendered bycustom functions: CreateContainer, CreateHeader, and CreateItem. TheCreateContainer function listed in Figure 6 is a fairly simple function thatdoes little more than instantiate a Panel control and set its properties tosome proper defaults. This panel will act as the container for the otherelements of the HoverList control. Many of the HoverList?s properties are pipedthrough to be managed by the Panel control.

 

Private Function CreateContainer() As Panel

   Dim pnl As New Panel

   pnl.ID = Me.ID

   pnl.Style(HtmlTextWriterStyle.Padding) = _

       Padding.ToString

   pnl.HorizontalAlign =Me.HorizontalAlign

   pnl.BorderColor =Me.BorderColor

   pnl.BorderStyle = Me.BorderStyle

   pnl.BorderWidth =Me.BorderWidth

   pnl.Width = Me.Width

   pnl.Height = Me.Height

   pnl.Visible =Me.Visible

   pnl.Enabled =Me.Enabled

   pnl.ToolTip =Me.ToolTip

   Return pnl

End Function

Figure 6: TheCreateContainer function instantiates a Panel control to contain the childcontrols that make up the HoverList control.

 

If the application developer has set the ShowHeaderproperty of the HoverList control to True, then the CreateHeader function iscalled to generate the header area of the control. As demonstrated here, theheader area is nothing more than a Label control:

 

Private Sub CreateHeader(ByVal pnl As Panel)

   Dim lbl As Label =_lblHeader

   lbl.Text =Me.HeaderText & "<br />" 'For Firefox

   lbl.Width = NewUnit(100, UnitType.Percentage)

   lbl.BackColor =Me.HeaderBackColor

   lbl.Font.CopyFrom(Me.HeaderFont)

   lbl.ForeColor =Me.HeaderForeColor

   pnl.Controls.Add(lbl)

End Sub

 

The For loop shown in Figure 5 loops through each ListItemmanaged by the base ListControl class and renders each item individually byinvoking the CreateItem subroutine shown in Figure 7. This is what makes up thebulk of the control?s final rendered appearance.

 

Private Sub CreateItem(ByVal pnl As Panel, _

 ByVal li As ListItem)

 

 Dim lbl As New Label

 lbl.Text = li.Text &"<br />" 'For Firefox

 lbl.Width = New Unit(100,UnitType.Percentage)

 lbl.BackColor =Me.BackColor

 lbl.ForeColor =Me.ForeColor

 If li.Enabled Then

     lbl.Style(HtmlTextWriterStyle.Cursor) = "hand"

     lbl.Attributes("onMouseOver")= _

         "this.style.backgroundColor='" & _

         ColorTranslator.ToHtml(Me.HoverBackColor) _

         &"';" & "this.style.color='" & _

         ColorTranslator.ToHtml(Me.HoverForeColor) _

         &"';"

     lbl.Attributes("onMouseOut")= _

         "this.style.backgroundColor='" & _

         ColorTranslator.ToHtml(Me.BackColor) _

         &"';" & "this.style.color='" & _

         ColorTranslator.ToHtml(Me.ForeColor) & "';"

     lbl.Attributes("onClick") = _

         Page.ClientScript.GetPostBackClientHyperlink(Me, _

         li.Value)

 End If

 lbl.Font.CopyFrom(Me.Font)

 pnl.Controls.Add(lbl)

End Sub

Figure 7: TheCreateItem subroutine is invoked once for every ListItem that?s managed by theunderlying ListControl class. It instantiates and configures a Label control torepresent each ListItem.

 

Like the header area, each ListItem will be represented bya Label control. The CreateItem subroutine instantiates and configures a Labelcontrol to represent the ListItem parameter. Because the ASP.NET 2.0 version ofthe standard ListIem class now includes an Enabled property, it is used here torepresent a richer rendering for enabled items. For example, the Label?s Cursorstyle is set to ?hand? so that the mouse cursor will appear as a hand icon whenmoved over enabled items at run time (as shown in Figure 1).

 

The CreateItem subroutine shown in Figure 7 continues byadding client-side onMouseOver and onMouseOut events to the Label control toimplement the unique color changes that occur when the mouse moves over theitem at run time. These client-side events use JavaScript to change the textcolor and the background color of the label as the mouse enters and leaves itsboundaries.

 

The final client-side event to be wired up is the onClickevent. When the user clicks on the label, the page will post back and,ultimately, the OnSelectedItemChanged event will fire, allowing the page torespond to the user?s command. ASP.NET?s GetPostBackClientHyperlink methoddynamically generates the code that invokes the post back. This method usesASP.NET?s adaptive rendering engine to generate proper PostBack code, no matterwhich browser or device is being utilized by the end user.

 

Finally, the selected font is applied to the label, andthe label is added to the containing panel?s control collection. Then the panel?scomplete control tree is finally output when execution returns to the last lineof the render function of Figure 5.

 

Conclusion

The HoverList is a nice control to have around to add aquick and functional menu of options to the user. Its visual interactivity addsa bit of spice to a Web site without being overly flashy. The design-timeexperience is quite similar to that of a ListBox, so the learning curve shouldbe small.

 

By inheriting from ListControl, rich functionality can betaken advantage of with little or no code necessary ? such as data binding andpractical design-time features. Sprinkle in a touch of rendering code with adash of client-side JavaScript code and a useful little control starts toemerge. Using the techniques demonstrated in this article, you can extend theHoverList control with enhanced functionality, or use the knowledge to create acustom control that lives up to your own dreams ? or at least your manager?srequirements.

 

The source code forthe HoverList control (in both VB and C#) is available for download.

 

Steve C. Orr is anMCSD and a Microsoft MVP in ASP.NET. He?s been developing software solutionsfor leading companies in the Seattlearea for more than a decade. When he?s not busy designing software systems orwriting about them, he can often be found loitering at local user groups andhabitually lurking in the ASP.NET newsgroup. Find out more about him at http://SteveOrr.netor e-mail him at mailto:Steve@Orr.net.

 

 

 

Add a Comment

There are no comments to display. Be the first one!
You must log on before posting a comment.

Are you a new visitor? Register Here

advertisement




Comments from the DevConnections Community

Join our community of development pros.

Windows problem

I all, I have a problem on my Windows Vista that began afetr the purchase of an external Hard Disk Freecom. A few days afetr the purchase I discon...

Most Recent Posts

GOOGLE LINKS
SPONSORED LINKS
FEATURED LINKS