Wrox Home  
Search
Professional ASP.NET 2.0 Server Control and Component Development
by Shahram Khosravi
August 2006, Paperback


Developing a Custom WebPartChrome

This section develops a custom WebPartChrome named CustomWebPartChrome that derives from the WebPartChrome base class and extends its functionality to add support for the following features:

  • Automatic rendering of a logo in the title bar of every WebPart control that the associated zone contains
  • Using the DHTML feature known as transition to provide an animated effect when the user moves the mouse pointer over the logo

CustomWebPartChrome exposes two new properties named MouseOverImageUrl and MouseOutImageUrl that the page developer must set to the URLs of the images that the CustomWebPartChrome control will render when the user moves the mouse pointer over and out of the control, respectively. In other words, CustomWebPartChrome switches from one image to another when the user moves the mouse pointer over or out of the control.

The revealTrans function is a standard IE function that provides an animated effect when CustomWebPartChrome switches from one image to another. This function takes two arguments. The first argument specifies the duration of the transition or animation. The second argument determines the type of transition or animation.

CustomWebPartChrome exposes an enumeration property of type Transition named Transition. The following code listing shows the possible values of this property. Each value introduces a different animation flavor.

public enum Transition
{
 BoxIn, BoxOut, CircleIn, CircleOut, WipeUp, WipeDown, WipeRight, WipeLeft,
 VerticalBlinds, HorizontalBlinds, CheckerboardAcross, CheckerboardDown,
 RandomDissolve, SplitVerticalIn, SplitVerticalOut, SplitHorizontalIn,
 SplitHorizontalOut, StripsLeftDown, StripsLeftUp, StripsRightDown,
 StripsRightUp, RandomBarsHorizontal, RandomBarsVertical, RandomTransition
}
Interested readers are referred to the MSDN Web site for the complete information about the possible values of the transition parameter of the revealTrans method.

As Listing 6 shows, CustomWebPartChrome overrides the PerformPreRender method of its base class to render the client script that supports the DHTML transition feature. This method first iterates through the WebPart controls that the associated zone contains to dynamically generate the client script that supports the transition effect. As Listing 3 shows, the RenderWebPart method of the WebPartChrome assigns the return value of the GetWebPartTitleClientID method to the id HTML attribute of the table cell that contains the title text for the WebPart control. PerformPreRender passes the return value of this method to the getElementById method of the document object to return a reference to the table cell that contains the title text:

js += ("titleBar = document.getElementById('" + 
	GetWebPartTitleClientID(webPart) + "');\n");

It then generates the script that returns a reference to the first child element of the table cell:

js += "titleBarFirstChild = titleBar.childNodes[0];\n";

Next, the method generates the script that creates an <img> HTML element and inserts this element as the first child element of the table cell. This ensures the logo will always appear on the top-left corner of the WebPart control:

js += "img = document.createElement('img');\n";
js += "titleBar.insertBefore(img,titleBarFirstChild);\n";

It then generates the script that registers the JavaScript functions MouseOverCallback and MouseOutCallback for the onmouseover and onmouseout client-side events of the logo:

js += "img.onmouseover = MouseOverCallback;\n";
js += "img.onmouseout = MouseOutCallback;\n";

Next, the method generates the script that stores the values of the MouseOutImageUrl and MouseOverImageUrl properties. As you'll see later, the MouseOverCallback and MouseOutCallback JavaScript function uses these values to switch between the two versions of the logo:

    js += ("img.srcOut = '" + MouseOutImageUrl + "';\n");
    js += ("img.srcOver = '" + MouseOverImageUrl + "';\n");

Then it generates the script that assigns the revealTrans filter to the filter property of the style object and uses the values of the Duration and Transition properties to set the duration and transition parameters of the filter:

js += ("img.style.filter = 'revealTrans(duration=" + 
	Duration.ToString() + ",transition=" + 
((int)Transition).ToString() + ")';\n");

Once the script is created, PerformPreRender calls the RegisterStartupScript method to register the script with the containing page. As discussed in Chapter 26 "Developing Ajax-Enabled Controls and Components: Client-Side Functionality" of the book Professional ASP.NET 2.0 Server Control and Component Development (Wrox, August 2006, ISBN: 0-471-79350-7), the containing page renders all the registered scripts when it enters its rendering phase.

Zone.Page.ClientScript.RegisterStartupScript(typeof(CustomWebPartChrome), 
  typeof(CustomWebPartChrome).FullName, js);

Finally, the method calls the RegisterClientScriptInclude method to have the containing page render a reference to the CustomWebPartChrome.js script file:

Zone.Page.ClientScript.RegisterClientScriptInclude(
  typeof(CustomWebPartChrome).FullName, "CustomWebPartChrome.js");
Listing 6: The PerformPreRender method
public override void PerformPreRender()
{
  base.PerformPreRender();
  string js =
    "<script language='javascript'>\n\t" +
      "var titleBar;\n" +
      "var titleBarFirstChild;\n" +
      "var img;\n";
  foreach (WebPart webPart in Zone.WebParts)
  {
    js += ("titleBar = document.getElementById('" + 
		GetWebPartTitleClientID(webPart) + "');\n");
    js += "titleBarFirstChild = titleBar.childNodes[0];\n";
    js += "img = document.createElement('img');\n";
    js += "titleBar.insertBefore(img,titleBarFirstChild);\n";
    js += ("img.src = '" + MouseOutImageUrl + "';\n");
    js += ("img.srcOut = '" + MouseOutImageUrl + "';\n");
    js += ("img.srcOver = '" + MouseOverImageUrl + "';\n");
    js += ("img.style.filter = 'revealTrans(duration=" + Duration.ToString() + 
		",transition=" + ((int)Transition).ToString() + ")';\n");
    js += "img.onmouseover = MouseOverCallback;\n";
    js += "img.onmouseout = MouseOutCallback;\n";
  }
  js += "</script>";
  Zone.Page.ClientScript.RegisterStartupScript(typeof(CustomWebPartChrome), 
 	typeof(CustomWebPartChrome).FullName, js);
   
  Zone.Page.ClientScript.RegisterClientScriptInclude(
	typeof(CustomWebPartChrome).FullName, "CustomWebPartChrome.js");
}

Listing 7 shows the JavaScript functions that're called when the user moves the mouse pointer out of and over the control.

Listing 7: The mouse movement JavaScript functions
function MouseOverCallback (img,mouseOverImageUrl)
{ 
  img.filters[0].apply();
  img.src = mouseOverImageUrl;
  img.filters[0].play();   
}
function MouseOutCallback (img,mouseOutImageUrl)
{ 
  img.filters[0].stop();
  img.src = mouseOutImageUrl;
}

The img JavaScript object references the <img> HTML element. This object exposes a collection property named filters that contains all the filters defined in the style attribute of the <img> element. In this case, this collection contains a single item, the transition filter. The filter JavaScript object exposes three important methods, apply, play, and stop.

As Listing 7 shows, the MouseOverCallback calls the apply method of the filter object to take a snapshot of the current image that the <img> element displays:

img.filters[0].apply();

It switches to the new image:

img.src = mouseOverImageUrl;

It then calls the play method of the filter object to start the animation:

img.filters[0].play();

As Listing 7 shows, the MouseOutCallback method calls the stop method of the filter object to stop the animation:

img.filters[0].stop();

It then switches to the new image

img.src = mouseOutImageUrl;

When you develop a custom WebPartChrome, you must also develop a custom WebPartZoneBase that uses your custom WebPartChrome to render its WebPart controls. However, before getting into the implementation of the custom WebPartZoneBase that uses CustomWebPartChrome, you'll need to override one more method of the WebPartChrome base class, RenderWebPart, to ensure that the CustomWebPartChrome is used by your custom WebPartZoneBase.

Listing 8 illustrates the implementation of the RenderWebPart method of the CustomWebPartChrome. As this listing shows, the method ensures the associated zone is of type CustomWebPartZone before it calls the RenderWebPart method of its base class to render the specified WebPart control.

Listing 8: The RenderWebPart method of the CustomWebPartChrome
public override void RenderWebPart(HtmlTextWriter writer, WebPart webPart)
{
  if (this.Zone.GetType() == typeof(CustomWebPartZone))
    base.RenderWebPart(writer, webPart);
}

CustomWebPartZone

As discussed, RenderBody delegates the responsibility of rendering all the WebPart controls that it contains to a single instance of WebPartChrome. WebPartZoneBase exposes a protected virtual method named CreateWebPartChrome whose default implementation returns an instance of the WebPartChrome class as shown in the following code listing:

protected virtual WebPartChrome CreateWebPartChrome()
{
  return new WebPartChrome(this, base.WebPartManager);
}

CustomWebPartZone is a custom zone that uses CustomWebPartChrome to render its WebPart controls. The CustomWebPartZone custom zone exposes the same four properties that CustomWebPartChrome does: MouseOverImageUrl, MouseOutImageUrl, Duration, and Transition. This custom zone overrides the CreateWebPartChrome method of its base class to instantiate and to return an instance of the CustomWebPartChrome as shown in Listing 9.

Listing 9: The CreateWebPartChrome method
protected override WebPartChrome CreateWebPartChrome()
{
  CustomWebPartChrome webPartChrome = 
		new CustomWebPartChrome(this, this.WebPartManager);
  webPartChrome.MouseOutImageUrl = MouseOutImageUrl;
  webPartChrome.MouseOverImageUrl = MouseOverImageUrl;
  webPartChrome.Duration = Duration;
  webPartChrome.Transition = Transition;
  return webPartChrome;
}

CreateWebPartChrome creates a CustomWebPartChrome and assigns the values of the MouseOverImageUrl, MouseOutImageUrl, Duration, and Transition properties of the CustomWebPartZone control to the respective properties of the newly created CustomWebPartChrome object.

Using the CustomWebPartChrome Control

Listing 10 contains a Web page that uses the CustomWebPartZone control and CustomWebPartChrome chrome. Notice that the page sets the values of the MouseOutImageUrl, MouseOverImageUrl, Duration, and Transition properties of the CustomWebPartZone control. Figure 1 shows what the users see on their browsers. Notice that every control added to the CustomWebPartZone automatically contains the logo image in its title bar. When the user moves the mouse pointer over the logo, the WebPart control provides an animated effect.

Listing 10: A Web page that uses the CustomWebPartZone control
<%@ Page Language="C#" %>
<%@ Register TagPrefix="custom" Namespace="CustomComponents" %>
<html xmlns="http://www.w3.org/1999/xhtml">
<body>
  <form id="form1" runat="server">
    <asp:WebPartManager runat="server" ID="mgr" />
    <custom:CustomWebPartZone runat="server" ID="zone1" 
    MouseOutImageUrl="WroxOut.bmp"
    MouseOverImageUrl="WroxOver.bmp" Duration="0.4" Transition="CircleIn">
      <ZoneTemplate>
        <asp:DropDownList runat="server" ID="ddl" />
        <asp:Calendar runat="server" ID="cal" />
      </ZoneTemplate>
    </custom:CustomWebPartZone>
  </form>
</body>
</html>
0471793507 : Professional ASP.NET 2.0 Server Control and Component Development : Figure 1
Figure 1

This article is adapted from Chapter 32 "Developing Custom WebPartZoneBase Controls" of the book Professional ASP.NET 2.0 Server Control and Component Development, by Dr. Shahram Khosravi (Wrox, August 2006, ISBN: 0-471-79350-7). Shahram is a senior software engineer, consultant, author, and instructor specializing in ASP.NET, Web services, .NET technologies, XML technologies, ADO.NET, C#, 3D computer graphics, Human Interface (HI) usability, and design patterns. He has more than 10 years of experience in object-oriented analysis, design, and programming. Shahram has written articles on the .NET Framework, ADO.NET, ASP.NET, and XML technologies for industry leading magazines such as Dr. Dobb's Journal, asp.netPRO magazine, and Microsoft MSDN Online.