Chapter 27. Introduction to Web Parts

<feature><title>In this Chapter</title> <objective>

Overview of the Web Part Framework

</objective>
<objective>

Creating a Simple Web Part Application

</objective>
<objective>

Using Catalog Zones

</objective>
<objective>

Using Editor Zones

</objective>
<objective>

Using Connections Zones

</objective>
<objective>

Summary

</objective>
</feature>

The ASP.NET Web Part Framework enables you to build web applications that can be personalized by users at runtime. A Web Part application can be personalized by individual users or the application can be personalized by a single administrator for everyone.

You can take advantage of Web Parts to build personalizable portal applications like My Yahoo! (http://my.yahoo.com) or My MSN (http://my.msn.com). Users of these applications can customize both the content and appearance of the application by interacting with a web page. For example, you can select the content you want to see from categories of content such as News, Sports, and Weather (see Figure 27.1). You can also arrange the content on a page in the manner that is most relevant to you (see Figure 27.2).

Selecting content at My MSN.

Figure 27.1. Selecting content at My MSN.

Arranging Content at My Yahoo!.

Figure 27.2. Arranging Content at My Yahoo!.

Most large companies have internal website portals. You can take advantage of Web Parts to enable the individual employees of your company to customize the portal pages in the way that is most relevant to them. For example, a software tester might want a home page that displays a list of the most recent bugs. A marketing person, on the other hand, might want to see a news feed and stock ticker.

The Web Part Framework also can be used to build applications that can be customized by one or more administrators for everyone. Imagine, for example, that you want to build and sell a customized web store to your clients. If you build your application by using Web Parts, your clients can customize the application’s appearance from their browsers without any technical knowledge.

In this chapter, you are introduced to the Web Part Framework. You learn how to build simple Web Parts and add the Web Parts to different zones in a page. You also learn how to enable users to edit Web Part properties from a Web Form page. Finally, you learn how you can connect Web Parts to communicate information from one Web Part to another.

Overview of the Web Part Framework

A Web Part is an ASP.NET control that is contained within a Web Part Zone. Any ASP.NET control can be used as a Web Part, including any standard ASP.NET control such as the GridView, Image, or LinkButton control. You can also create a Web Part by creating a new User control or a new custom Web control.

Note

ASP.NET 2.0 Web Parts will be used in the next version of Windows Sharepoint Services (WSS) and Microsoft Office Sharepoint Portal Server (SPS). The good news is that if you develop Web Parts for the ASP.NET 2.0 Framework, then the Web Parts will work with the new versions of these products when they are released. The bad news is that ASP.NET 2.0 Web Parts are not compatible with the current implementation of Web Parts used in these two products.

Because you can create a new Web Part by creating a new control, a Web Part can do anything you want. You can create an Email Client Web Part, a Random Quotation of the Day Web Part, a Shopping Cart Web Part, or a Task List Web Part. Anything you can do in the ASP.NET Framework, you can do with Web Parts.

When you add an ASP.NET control to a Web Part Zone, the control automatically gets several special capabilities. For example, you can drag and drop a Web Part from one Web Part Zone to another. You can minimize and maximize a Web Part. You can modify the properties of a Web Part and the modifications are automatically saved.

Note

The next chapter is devoted exclusively to the topic of building Web Parts.

Web Parts are just one type of control included in the Web Part Framework. You can use several different types of parts when building a Web Part page. You can also add several different types of zones to a Web Part page.

Web Part Zones

When you build a page that contains Web Parts, you divide the page into different zones. Each zone is responsible for managing and rendering a particular type of part. There are four standard types of zones included in the Web Part Framework:

  • Web Part Zones—This type of zone is used to render Web Parts. You can add Web Parts to a Web Part Zone and drag and drop Web Parts between different Web Part Zones.

  • Editor Zones—This type of zone is used to render Editor Parts. Use Editor Parts to enable a user to edit Web Part properties.

  • Catalog Zones—This type of zone is used to render Catalog Parts. Use Catalog Parts to display lists of Web Parts that a user can add to a page.

  • Connections Zones—This type of zone is used to display an interface that enables users to connect Web Parts dynamically.

Note

You can extend the Web Part Framework with custom zones. We’ll explore this option in Chapter 30, “Extending the Web Part Framework.”

Every page that contains Web Parts contains at least one Web Part Zone. A Web Part Zone is used to lay out the Web Parts on a page.

The other types of zones are known collectively as tool zones. Adding a tool zone to a page is optional. If you don’t want a user to add new Web Parts to a page, then don’t include a Catalog Zone in the page. If you don’t want a user to be able to edit or connect Web Parts, then don’t add Editor or Connections Zones to a page.

Web Part Display Modes

By default, when you first open a page that contains Web Parts, the only type of zone that is rendered is Web Part Zones. To display the other types of zones, you must change the page’s Display Mode.

At any time, a page can be in one of the following Display Modes:

  • Browse—The default mode. In this mode, you cannot rearrange or edit Web Parts.

  • Design—In this mode, you can drag and drop Web Parts from one Web Part Zone to another.

  • Edit—In this mode, you can edit a Web Part’s properties by using one or more Editor Parts.

  • Catalog—In this mode, you can add new Web Parts to a page from one or more Catalog Parts.

  • Connect—In this mode, you can create dynamic connections between Web Parts.

A page that contains Web Parts can be in only one Display Mode at a time. If you switch to Edit Display Mode, then the contents of any Editor Zones are rendered and you can edit Web Parts. If you switch to Catalog Display Mode, then the contents of any Catalog Zones are rendered and you can add new Web Parts. However, you cannot set a page to both Edit and Catalog Display Mode at the same time.

Note

You can extend the Web Part Framework with custom Display Modes. We’ll explore this option in Chapter 30.

Web Part Personalization

When a user makes changes to a Web Part’s properties, the Web Part Framework automatically saves these changes. For example, a user can add one or more Web Parts to a page and arrange the Web Parts with a particular layout. If the user returns to the page in the future, the Web Parts will remember the layout. This feature of the Web Part Framework is called personalization.

The Web Part Framework supports two types of personalization: User and Shared. By default, all changes made to a Web Parts page have User scope. Changes are scoped to a particular user, which enables each user to personalize the same page in different ways.

The Web Part Framework also supports Shared scope personalization. An administrator of a Web Part application can make changes that have an effect on everyone who uses the application. For example, an administrator might want to add a standard set of Web Parts to a page and prevent individual users from removing them.

Note

This chapter sticks to User scope personalization. In Chapter 29, “Personalizing Web Parts,” the topic of User and Shared scope personalization is examined in detail.

For personalization to work, the Web Part Framework must have a method of identifying users. The default personalization provider included with the Web Part Framework requires that users be authenticated. If you use the default provider, then an unauthenticated user can browse, but not customize, a Web Part application. (In Chapter 29, you learn how to create a custom personalization provider.)

Warning

You must enable authentication for your application for many of the sample pages in this chapter to work. By default, Windows Authentication is enabled. For more information about enabling authentication, see Chapter 20, “Using the Login Controls.”

Creating a Simple Web Part Application

Let’s get our hands dirty by building a simple Web Part application. In this section, you’ll create a minimal Web Part application that consists of a single page. It illustrates how to use three of the different types of zones: Web Part Zones, Editor Zones, and Catalog Zones.

You start by creating two painfully simple Web Parts. The easiest way to create new Web Parts is to create User Controls. The User Controls contained in Listing 27.1 and Listing 27.2 serve as the Web Parts.

Note

To learn more about User Controls, see Chapter 7, “Creating Custom Controls with User Controls.”

Example 27.1. FirstSimplePart.ascx

<%@ Control Language="VB" ClassName="FirstSimplePart" %>

 <h1>First Simple Part</h1>

Example 27.2. SecondSimplePart.ascx

<%@ Control Language="VB" ClassName="SecondSimplePart" %>

 <h1>Second Simple Part</h1>

These simple Web Parts both consist of nothing more than a single line of text. You can, of course, create more complicated Web Parts with User controls. For example, you can create a User control that contains a GridView control bound to some database data. Or, you can create a User Control that calls a remote web service to display the current weather. In this section, however, we keep things simple.

Next, you need to create the page that you’ll use to host your Web Parts. Every page that contains Web Parts must, at a minimum, have one WebPartManager control and one or more WebPartZone controls.

Every page that contains Web Parts must include one, and only one, WebPartManager control. The WebPartManager control is responsible for tracking the state of all the Web Parts on the page. The WebPartManager control must appear before any other Web Parts on the page. For this reason, it is a good idea to place the WebPartManager control immediately after the server-side form control in the page.

The WebPartZone controls are used to mark the different areas of the page that can contain Web Parts. They are used to lay out Web Parts on a page. You can add as many WebPartZone controls to a page as you want.

Tip

You can add the WebPartManager control and the WebPartZone controls to a Master Page. This is useful when you want to automatically include a WebPartManager and WebPartZone controls in multiple content pages without explicitly declaring the controls in each page.

You’ll build the page in stages. First, create a page that contains a WebPartManager control and two Web Part Zone controls (see Listing 27.3).

Example 27.3. SimpleWebParts1.aspx

<%@ Page Language="VB" %>
<%@ Register TagPrefix="user" TagName="FirstSimplePart"
Src="~/FirstSimplePart.ascx" %>
<%@ Register TagPrefix="user" TagName="SecondSimplePart"
Src="~/SecondSimplePart.ascx" %>
<!DOCTYPE html
        PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
    <style type="text/css">
        .column
        {
            float:left;
            width:40%;
            height:200px;
            margin-right:10px;
            border:solid 1px black;
            background-color: white;
        }
        html
        {
            background-color:#eeeeee;
        }
    </style>
    <title>Simple Web Parts 1</title>
</head>
<body>
    <form id="form1" runat="server">
    <asp:WebPartManager
        id="WebPartManager1"
        Runat="server" />

        <asp:WebPartZone
            id="WebPartZone1"
            CssClass="column"
            Runat="server">
            <ZoneTemplate>
            <user:FirstSimplePart
                id="FirstSimplePart1"
                Title="First Web Part"
                Description="Our first simple Web Part"
                Runat="server" />
            <user:SecondSimplePart
                id="SecondSimplePart1"
                Title="Second Web Part"
                Description="Our second simple Web Part"
                Runat="server" />
            </ZoneTemplate>
        </asp:WebPartZone>

        <asp:WebPartZone
            id="WebPartZone2"
            CssClass="column"
            Runat="server" />

    </form>
</body>
</html>

Notice that the page in Listing 27.3 contains a WebPartManager control immediately after the server-side <form> tag. If you neglected to add the WebPartManager control to the page, you would get an exception when you opened the page.

The page also contains two Web Part Zones. The first Web Part Zone contains the two simple Web Parts that you created earlier. The Web Parts are listed in the WebPartZone control’s ZoneTemplate. The second Web Part Zone is empty.

Notice that the two simple Web Parts are both provided with a Title and Description attribute. The Title attribute appears in the Web Part’s title bar, and the description appears as a tool tip when you hover your mouse over a Web Part.

Visual Web Developer Note

If you open the page in Listing 27.3 in Source View, you’ll notice a green squiggle warning beneath the Title and Description attributes. You can safely ignore this warning. The warning appears because these aren’t really properties of the User Controls. Technically, the Title and Description properties are expando properties that are interpreted by the Web Part Framework at runtime.

Note

To keep things simple, the two User controls are registered with the <%@ Register %> directive at the top of the page. Another option would be to register the User Controls in your application’s Web Configuration file and make the controls automatically available in any page in your application. To learn more about User controls see Chapter 7.

When you open the page in Listing 27.3 in a browser, you see the page in Figure 27.3. At the moment, you can’t do very much with the page. The only thing you can do is open each of the Web Part’s menus. Each Web Part menu has two options: Minimize and Close. Minimizing a Web Part shrinks a Web Part to its title bar. If you close a Web Part, then the Web Part is no longer rendered to the page.

The Simple Parts 1 page.

Figure 27.3. The Simple Parts 1 page.

Web Standards Note

The page in Listing 27.3 uses an internal Cascading Style Sheet to position the two Web Part Zones. The zones are positioned with a liquid layout. Both Web Part Zones are floated to the left with the help of a CSS class named column.

You can, of course, lay out the Web Part Zones in a page by using an HTML table. However, you should feel very guilty about even thinking about doing it because you should strive to use HTML tables only when displaying tabular data and not for layout.

Note

How do you open a Web Part after you close it? You use the PageCatalogPart control that is discussed later in this section.

If you prefer, you can prevent users from closing Web Parts by disabling the Close menu option. Set the CloseVerb-Visible property on the WebPartZone control to the value false.

To do anything interesting in a page that contains Web Parts, you need to add a mechanism to the page that enables users to switch between different Web Part Display Modes. The WebPartManager control is responsible for setting the Display Mode. You can set the Display Mode by taking advantage of the WebPartManager control’s DisplayMode property like this:

WebPartManager1.DisplayMode = WebPartManager.DesignDisplayMode

This line of code sets the page to Design Display Mode. Each of the standard Web Part Display Modes is represented by a shared (static) field exposed by the WebPartManager class. (Display Modes are not represented by an enumeration because you can create custom Display Modes.)

Here’s another method of setting the Display Mode:

WebPartManager1.DisplayMode = WebPartManager1.DisplayModes("Design")

This line of code also sets the page Display Mode to Design Display Mode. However, in this case, the DisplayModes property is used as the value of the assignment. The DisplayModes property exposes a collection of all the Display Modes that the WebPartManager control knows. We’ll use this second method of setting the Display Mode because it makes it possible to avoid using a Visual Basic SELECT...CASE statement.

The page in Listing 27.4 is the same as the previous page in Listing 27.3 with one addition. This new page contains an ASP.NET menu control that enables you to switch the Display Mode of the page to Design Display Mode. (The modifications are emphasized in bold.)

Example 27.4. SimpleWebParts2.aspx

<%@ Page Language="VB" %>
<%@ Register TagPrefix="user" TagName="FirstSimplePart"
Src="~/FirstSimplePart.ascx" %>
<%@ Register TagPrefix="user" TagName="SecondSimplePart"
Src="~/SecondSimplePart.ascx" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<script runat="server">

    Sub Menu1_MenuItemClick(sender As Object, e As MenuEventArgs)
        WebPartManager1.DisplayMode = WebPartManager1.DisplayModes(e.Item.Text)
    End Sub
</script>

<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
    <style type="text/css">
        .column
        {
            float:left;
            width:40%;
            height:200px;
            margin-right:10px;
            border:solid 1px black;
            background-color: white;
        }
        .menu
        {
            margin:5px 0px;
        }
        html
        {
            background-color:#eeeeee;
        }
    </style>
    <title>Simple Web Parts 2</title>
</head>
<body>
    <form id="form1" runat="server">
    <asp:WebPartManager
        id="WebPartManager1"
        Runat="server" />

        <asp:Menu
            id="Menu1"
            OnMenuItemClick="Menu1_MenuItemClick"
            Orientation="Horizontal"
            CssClass="menu"
            Runat="server">
            <Items>
            <asp:MenuItem Text="Browse" />
            <asp:MenuItem Text="Design" />
            </Items>
        </asp:Menu>

        <asp:WebPartZone
            id="WebPartZone1"
            CssClass="column"
            Runat="server">
            <ZoneTemplate>
            <user:FirstSimplePart
                id="FirstSimplePart1"
                Title="First Web Part"
                Description="Our first simple Web Part"
                Runat="server" />
            <user:SecondSimplePart
                id="SecondSimplePart1"
                Title="Second Web Part"
                Description="Our second simple Web Part"
                Runat="server" />
            </ZoneTemplate>
        </asp:WebPartZone>

        <asp:WebPartZone
            id="WebPartZone2"
            CssClass="column"
            Runat="server" />

    </form>
</body>
</html>

After you open the page in Listing 27.4, you can click the Design menu option and drag and drop the Web Parts between the two Web Part Zones (see Figure 27.4). When you set a page to be in Design Display Mode, the Web Part Framework automatically generates the necessary client-side JavaScript code for moving Web Parts.

Dragging a Web Part between Web Part Zones.

Figure 27.4. Dragging a Web Part between Web Part Zones.

Web Standards Note

Performing a drag-and-drop operation requires using a mouse. This requirement violates Section 508 and WCAG accessibility guidelines because a person with limited mobility might need to interact with a web page from the keyboard. You can satisfy these accessibility requirements by adding a LayoutEditorPart control to the page. The LayoutEditorPart control enables you to move Web Parts around a page without using a mouse.

It is important to understand that the Web Part Framework automatically saves the state of all the Web Parts in a page. In other words, if you rearrange the Web Parts, the Web Parts retain their new positions when you return to the page in the future.

Note

In this section, I’m assuming that Windows Authentication is enabled for your application (which is the default Authentication mode). If your Web Parts are forgetting their positions on a page after you close and re-open the page then, most likely, you are not being authenticated. For more information on configuring Authentication, see Part VI, “Security,” of this book.

You can also enable users to add new Web Parts to a page. To do this, you need to add a CatalogZone control that contains one or more Catalog Parts to the page. For example, the page in Listing 27.5 includes a Declarative Catalog Part which lists both the FirstSimplePart and SecondSimplePart Web Parts.

Example 27.5. SimpleWebParts3.aspx

<%@ Page Language="VB" %>
<%@ Register TagPrefix="user" TagName="FirstSimplePart"
Src="~/FirstSimplePart.ascx" %>
<%@ Register TagPrefix="user" TagName="SecondSimplePart"
Src="~/SecondSimplePart.ascx" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<script runat="server">

    Sub Menu1_MenuItemClick(ByVal sender As Object, ByVal e As MenuEventArgs)
        WebPartManager1.DisplayMode = WebPartManager1.DisplayModes(e.Item.Text)
    End Sub
</script>

<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
    <style type="text/css">
        .column
        {
            float:left;
            width:30%;
            height:200px;
            margin-right:10px;
            border:solid 1px black;
            background-color: white;
        }
        .menu
        {
            margin:5px 0px;
        }
        html
        {
            background-color:#eeeeee;
        }
    </style>
    <title>Simple Web Parts 3</title>
</head>
<body>
    <form id="form1" runat="server">
    <asp:WebPartManager
        id="WebPartManager1"
        Runat="server" />

        <asp:Menu
            id="Menu1"
            OnMenuItemClick="Menu1_MenuItemClick"
            Orientation="Horizontal"
            CssClass="menu"
            Runat="server">
            <Items>
            <asp:MenuItem Text="Browse" />
            <asp:MenuItem Text="Design" />
            <asp:MenuItem Text="Catalog" />
            </Items>
        </asp:Menu>

        <asp:WebPartZone
            id="WebPartZone1"
            CssClass="column"
            Runat="server" />

        <asp:WebPartZone
            id="WebPartZone2"
            CssClass="column"
            Runat="server" />

        <asp:CatalogZone
            id="CatalogZone1"
            CssClass="column"
            Runat="server">
            <ZoneTemplate>
            <asp:DeclarativeCatalogPart
                id="DeclarativeCatalogPart"
                Runat="server">
                <WebPartsTemplate>
                <user:FirstSimplePart
                    id="FirstSimplePart1"
                    Title="First Web Part"
                    Description="Our first simple Web Part"
                    Runat="server" />
                <user:SecondSimplePart
                    id="SecondSimplePart1"
                    Title="Second Web Part"
                    Description="Our second simple Web Part"
                    Runat="server" />
                </WebPartsTemplate>
            </asp:DeclarativeCatalogPart>
            <asp:PageCatalogPart
                id="PageCatalogPart1"
                Runat="server" />
            </ZoneTemplate>
        </asp:CatalogZone>

    </form>
</body>
</html>

The additions to Listing 27.5 are emphasized in bold. Notice that a new menu option has been added to the ASP.NET Menu control. The new menu option enables you to switch the page to Catalog Display Mode (see Figure 27.5).

Opening Catalog Display mode.

Figure 27.5. Opening Catalog Display mode.

Furthermore, a Catalog Zone has been added to the page. The Catalog Zone includes a DeclarativeCatalogPart which is used to list the two Web Parts that you can add to the page. The CatalogZone also includes a PageCatalogPart control, which is used to add closed Web Parts back to a page.

After you open the page in Listing 27.5 in a browser, you can click the Catalog menu option and add new instances of the two Web Parts to the page. Again, any changes you make to the page are saved automatically by the Web Part Framework.

Notice that you can now retrieve any Web Parts that you have closed on the page by taking advantage of the PageCatalogPart. If you close a Web Part by selecting a Web Part’s Close menu option, you can re-open the Web Part by clicking Catalog and selecting the closed Web Part from the list of Web Parts rendered by the Page Catalog Part control.

Note

The DeclarativeCatalogPart control does not enable you to drag and drop Web Parts onto the page. If you want to add drag-and-drop support or paging and sorting support or any other custom functionality to a Catalog Part, then you need to create a custom Catalog Part. This option is discussed in Chapter 30.

Finally, you can enable users to edit Web Parts. For example, Listing 27.6 contains a new Web Part named FeaturedBookPart. This Web Part displays information about a particular book.

Example 27.6. FeaturedBookPart.ascx

<%@ Control Language="VB" ClassName="FeaturedBookPart" %>
<script runat="server">

    Private _bookTitle As String = "Untitled"
    Private _category As BookCategory = BookCategory.Computers
    Private _bookDescription As String
    Private _onSale As Boolean

    Public Enum BookCategory
        Computers
        History
        Mystery
    End Enum

    <Personalizable()> _
    <WebBrowsable()> _
    <WebDisplayName("Title")> _
    <WebDescription("The title of the book")> _
    Public Property BookTitle() As String
        Get
            Return _bookTitle
        End Get
        Set(ByVal Value As String)
            _bookTitle = value
        End Set
    End Property

    <Personalizable()> _
    <WebBrowsable()> _
    <WebDisplayName("Category")> _
    <WebDescription("The category of the book")> _
    Public Property Category() As BookCategory
        Get
            Return _category
        End Get
        Set(ByVal Value As BookCategory)
            _category = value
        End Set
    End Property

    <Personalizable()> _
    <WebBrowsable()> _
    <WebDisplayName("Description")> _
    <WebDescription("The description of the book")> _
    Public Property BookDescription() As String
        Get
            Return _bookDescription
        End Get
        Set(ByVal Value As String)
            _bookDescription = value
        End Set
    End Property

    <Personalizable()> _
    <WebBrowsable()> _
    <WebDisplayName("On Sale")> _
    <WebDescription("Indicates that the book is on sale")> _
    Public Property OnSale() As Boolean
        Get
            Return _onSale
        End Get
        Set(ByVal Value As Boolean)
            _onSale = value
        End Set
    End Property

    Private Sub Page_PreRender()
        ltlBookTitle.Text = _bookTitle
        lblCategory.Text = _category.ToString()
        lblBookDescription.Text = _bookDescription
        lblOnSale.Visible = _onSale
    End Sub

</script>
<h1 class="bookTitle">
<asp:Literal
    ID="ltlBookTitle"
    runat="server"/>
</h1>
<asp:Label
    ID="lblCategory"
    CssClass="category"
    runat="server" />
<br />
<asp:Label
    ID="lblBookDescription"
    runat="server" />
<br />
<asp:Label
    ID="lblOnSale"
    Text="On Sale!"
    Visible="false"
    CssClass="onSale"
    runat="server" />

You should notice several things about the Web Part in Listing 27.6. Notice that each of its properties is decorated with the following attributes: Personalizable, WebBrowsable, WebDisplayName, WebDescription. The Web Part Framework automatically detects these attributes.

The most important attribute is the Personalizable attribute. Any property marked with the Personalizable attribute is automatically saved and loaded by the Web Part Framework. Because the BookTitle, BookCategory, BookDescription, and OnSale properties are all marked as Personalizable, any changes to these properties are saved by the Web Part Framework.

The remaining three attributes—WebBrowsable, WebDisplayName, and WebDescription—are used by the PropertyGridEditorPart control. Only properties marked with the WebBrowsable attribute are displayed in the property grid rendered by the PropertyGridEditorPart control. The WebDisplayName and WebDescription attributes determine the title and description displayed for the property in the property sheet. Both the WebDisplayName and WebDescription attributes are optional.

The page in Listing 27.7 illustrates how you can edit the FeaturedBookPart by using the PropertyGridEditorPart control (changes from the previous listings are emphasized in bold).

Example 27.7. SimpleWebParts4.aspx

<%@ Page Language="VB" %>
<%@ Register TagPrefix="user" TagName="FeaturedBookPart"
Src="~/FeaturedBookPart.ascx" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<script runat="server">

    Sub Menu1_MenuItemClick(ByVal sender As Object, ByVal e As MenuEventArgs)
        WebPartManager1.DisplayMode = WebPartManager1.DisplayModes(e.Item.Text)
    End Sub
</script>

<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
    <style type="text/css">
        .column
        {
            float:left;
            width:30%;
            height:200px;
            margin-right:10px;
            border:solid 1px black;
            background-color: white;
        }
        .menu
        {
            margin:5px 0px;
        }
        html
        {
            background-color:#eeeeee;
        }
        .bookTitle
        {
            font:bold 14px Arial,Sans-Serif;
            border-bottom:solid 1px black;
        }
        .category
        {
            font:italic 12px Arial,Sans-Serif;
        }
        .onSale
        {
            font:bold 14px Arial,Sans-Serif;
            background-color:yellow;
        }
    </style>
    <title>Simple Web Parts 4</title>
</head>
<body>
    <form id="form1" runat="server">
    <asp:WebPartManager
        id="WebPartManager1"
        Runat="server" />

        <asp:Menu
            id="Menu1"
            OnMenuItemClick="Menu1_MenuItemClick"
            Orientation="Horizontal"
            CssClass="menu"
            Runat="server">
            <Items>
            <asp:MenuItem Text="Browse" />
            <asp:MenuItem Text="Design" />
            <asp:MenuItem Text="Edit" />
            </Items>
        </asp:Menu>

        <asp:WebPartZone
            id="WebPartZone1"
            CssClass="column"
            Runat="server">
            <ZoneTemplate>
            <user:FeaturedBookPart
                id="FeaturedBookPart1"
                Title="Featured Book"
                Description="Displays featured book"
                Runat="server" />
            </ZoneTemplate>
        </asp:WebPartZone>

        <asp:WebPartZone
            id="WebPartZone2"
            CssClass="column"
            Runat="server" />

        <asp:EditorZone
            id="EditorZone1"
            CssClass="column"
            Runat="server">
            <ZoneTemplate>
            <asp:PropertyGridEditorPart
                id="PropertyGridEditorPart1"
                Runat="server" />
            </ZoneTemplate>
        </asp:EditorZone>
    </form>
</body>
</html>

When you open the page in Listing 27.7 in a browser, you can click the Edit menu option to switch the page into Edit Display Mode. When a page is in Edit Display Mode, you can edit particular Web Parts by selecting the Edit menu option from a Web Part menu. Selecting a Web Part to edit causes the EditorZone to render the PropertyGridEditorPart control (see Figure 27.6).

Opening the PropertyGridEditorPart control.

Figure 27.6. Opening the PropertyGridEditorPart control.

Notice that form fields are automatically generated for each of the properties that were marked as Personalizable. If you modify any of the properties and click either OK or Apply, the Web Part Framework automatically saves any changes to the properties.

Note

By default, changes to a Web Part property have User scope. In other words, each person who uses a Web Part page can customize it for his or her particular needs. You can also enable Shared scope personalization. In that case, changes to a Web Part property have an effect on all users. To learn more about personalization, see Chapter 29, “Personalizing Web Parts.”

Web Standards Note

The PropertyGridEditorPart automatically generates a form that is accessible to persons with disabilities. The form is contained in a fieldset element. Furthermore, label elements with for attributes are used to explicitly associate each label with each form field.

This section has walked you through the process of creating a basic page that contains Web Parts. The remainder of this chapter examines each of the tool zones included in the Web Part Framework in more detail. You’ll learn how to work with Catalog Zones, Editor Zones, and Connections Zones.

Using Catalog Zones

You use a Catalog Zone to list one or more catalogs of Web Parts that you can add to the page. The contents of a Catalog Zone appear only when a page is in Catalog Display Mode.

There are three standard types of Catalog Part controls included in the Web Part Framework: Declarative Catalog Parts, Page Catalog Parts, and Import Catalog Parts.

Using a Declarative Catalog Part

A Declarative Catalog Part contains a static list of controls that you can add to a page. You can supply the list of controls in two ways: The controls can be listed in the DeclarativeCatalogPart control’s <WebPartsTemplate> tag or you can list the Web Parts in an external file.

The page in Listing 27.8 illustrates how you can list the Web Parts displayed in the Declarative Catalog Part inline.

Example 27.8. DeclarativeCatalogPart1.aspx

<%@ Page Language="VB" %>
<%@ Register TagPrefix="user" TagName="FirstSimplePart"
Src="~/FirstSimplePart.ascx" %>
<%@ Register TagPrefix="user" TagName="SecondSimplePart"
Src="~/SecondSimplePart.ascx" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<script runat="server">
    Sub Menu1_MenuItemClick(ByVal sender As Object, ByVal e As MenuEventArgs)
        WebPartManager1.DisplayMode = WebPartManager1.DisplayModes(e.Item.Text)
    End Sub

</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
    <style type="text/css">
        .column
        {
            float:left;
            width:30%;
            height:200px;
            margin-right:10px;
            border:solid 1px black;
            background-color: white;
        }
        .menu
        {
            margin:5px 0px;
        }
        html
        {
            background-color:#eeeeee;
        }
    </style>
    <title>Declarative Catalog Part 1</title>
</head>
<body>
    <form id="form1" runat="server">
    <asp:WebPartManager
        id="WebPartManager1"
        Runat="server" />

        <asp:Menu
            id="Menu1"
            OnMenuItemClick="Menu1_MenuItemClick"
            Orientation="Horizontal"
            CssClass="menu"
            Runat="server">
            <Items>
            <asp:MenuItem Text="Browse" />
            <asp:MenuItem Text="Design" />
            <asp:MenuItem Text="Catalog" />
            </Items>
        </asp:Menu>

        <asp:WebPartZone
            id="WebPartZone1"
            CssClass="column"
            Runat="server" />

        <asp:WebPartZone
            id="WebPartZone2"
            CssClass="column"
            Runat="server" />

        <asp:CatalogZone
            id="CatalogZone1"
            CssClass="column"
            Runat="server">
            <ZoneTemplate>
            <asp:DeclarativeCatalogPart
                id="DeclarativeCatalogPart"
                Runat="server">
                <WebPartsTemplate>
                <user:FirstSimplePart
                    id="FirstSimplePart1"
                    Title="First Web Part"
                    Description="Our first simple Web Part"
                    Runat="server" />
                <user:SecondSimplePart
                    id="SecondSimplePart1"
                    Title="Second Web Part"
                    Description="Our second simple Web Part"
                    Runat="server" />
                </WebPartsTemplate>
            </asp:DeclarativeCatalogPart>
            </ZoneTemplate>
        </asp:CatalogZone>

    </form>
</body>
</html>

The page in Listing 27.8 contains a CatalogZone control. The CatalogZone control contains a ZoneTemplate, which includes the DeclarativeCatalogPart control. Finally, the DeclarativeCatalogPart control has a WebPartsTemplate that lists two Web Parts: the FirstSimplePart and SecondSimplePart.

If you open the page in your browser and click the Catalog menu link, you can see the list of controls rendered by the DeclarativeCatalogPart control. You can add a new part to the page by selecting any of the parts in the list, selecting a Web Part Zone from the drop-down list, and clicking the Add button (see Figure 27.7).

Using the DeclarativeCatalogPart control.

Figure 27.7. Using the DeclarativeCatalogPart control.

Note

The DeclarativeCatalogPart does not support paging or sorting. In Chapter 30, “Extending the Web Part Framework,” you learn how to create custom CatalogPart controls that support more functionality.

If you want to enable users to personalize multiple pages in an application, then it doesn’t make sense to list the Web Parts displayed by a Declarative Catalog Part in each page. You can use the DeclarativeCatalogPart control’s WebPartsListUserControlPath property to point to an external file that contains a list of Web Parts.

The DeclarativeCatalogPart in Listing 27.9 uses the WebPartsListUserControlPath property. The file that contains the list of Web Parts is contained in Listing 27.10. (Notice that the file is a User Control.)

Example 27.9. DeclarativeCatalogPart2.aspx

<%@ Page Language="VB" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<script runat="server">
    Sub Menu1_MenuItemClick(ByVal sender As Object, ByVal e As MenuEventArgs)
        WebPartManager1.DisplayMode = WebPartManager1.DisplayModes(e.Item.Text)
    End Sub

</script>

<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
    <style type="text/css">
        .column
        {
            float:left;
            width:30%;
            height:200px;
            margin-right:10px;
            border:solid 1px black;
            background-color: white;
        }
        .menu
        {
            margin:5px 0px;
        }
        html
        {
            background-color:#eeeeee;
        }
    </style>
    <title>Declarative Catalog Part 2</title>
</head>
<body>
    <form id="form1" runat="server">
    <asp:WebPartManager
        id="WebPartManager1"
        Runat="server" />

        <asp:Menu
            id="Menu1"
            OnMenuItemClick="Menu1_MenuItemClick"
            Orientation="Horizontal"
            CssClass="menu"
            Runat="server">
            <Items>
            <asp:MenuItem Text="Browse" />
            <asp:MenuItem Text="Design" />
            <asp:MenuItem Text="Catalog" />
            </Items>
        </asp:Menu>

        <asp:WebPartZone
            id="WebPartZone1"
            CssClass="column"
            Runat="server" />

        <asp:WebPartZone
            id="WebPartZone2"
            CssClass="column"
            Runat="server" />

        <asp:CatalogZone
            id="CatalogZone1"
            CssClass="column"
            Runat="server">
            <ZoneTemplate>
            <asp:DeclarativeCatalogPart
                id="DeclarativeCatalogPart"
                WebPartsListUserControlPath="~/WebPartList.ascx"
                Runat="server" />
            </ZoneTemplate>
        </asp:CatalogZone>

    </form>
</body>
</html>

Example 27.10. WebPartList.ascx

<%@ Control Language="VB" ClassName="WebPartList" %>
<%@ Register TagPrefix="user" TagName="FirstSimplePart" Src="~/FirstSimplePart.ascx" %>
<%@ Register TagPrefix="user" TagName="SecondSimplePart" Src="~/SecondSimplePart.ascx" %>

<user:FirstSimplePart
    id="FirstSimplePart1"
    Title="First Web Part"
    Description="Our first simple Web Part"
    Runat="server" />
<user:SecondSimplePart
    id="SecondSimplePart1"
    Title="Second Web Part"
    Description="Our second simple Web Part"
    Runat="server" />

Notice that the FirstSimplePart and SecondSimplePart controls are not registered in the page in Listing 27.9. However, you do need to register the controls in the file in Listing 27.10.

You can mix the Web Parts retrieved from an external file and the Web Parts declared inline. The Web Parts retrieved from the two sources are combined into one list.

Using a Page Catalog Part

The PageCatalogPart control displays all the Web Parts in the current page that have been closed. The control enables users to add closed Web Parts back to the original page.

Note

There is a difference between closing a Web Part and deleting a Web Part. You cannot delete a Web Part that is declared in a page, but you can close it. Furthermore, when you delete a Web Part from a page, all personalization state information is lost. When you close a Web Part, on the other hand, personalization data is not lost.

The page in Listing 27.11 demonstrates how you can use the PageCatalogPart control in a Catalog Zone.

Example 27.11. ShowPageCatalogPart.aspx

<%@ Page Language="VB" %>
<%@ Register TagPrefix="user" TagName="FirstSimplePart" Src="~/FirstSimplePart.ascx" %>
<%@ Register TagPrefix="user" TagName="SecondSimplePart" Src="~/SecondSimplePart.ascx" %>`1
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<script runat="server">

    Sub Menu1_MenuItemClick(ByVal sender As Object, ByVal e As MenuEventArgs)
        WebPartManager1.DisplayMode = WebPartManager1.DisplayModes(e.Item.Text)
    End Sub
</script>

<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
    <style type="text/css">
        .column
        {
            float:left;
            width:30%;
            height:200px;
            margin-right:10px;
            border:solid 1px black;
            background-color: white;
        }
        .menu
        {
            margin:5px 0px;
        }
        html
        {
            background-color:#eeeeee;
        }
    </style>
    <title>Show Page Catalog Part</title>
</head>
<body>
    <form id="form1" runat="server">
    <asp:WebPartManager
        id="WebPartManager1"
        Runat="server" />

        <asp:Menu
            id="Menu1"
            OnMenuItemClick="Menu1_MenuItemClick"
            Orientation="Horizontal"
            CssClass="menu"
            Runat="server">
            <Items>
            <asp:MenuItem Text="Browse" />
            <asp:MenuItem Text="Design" />
            <asp:MenuItem Text="Catalog" />
            </Items>
        </asp:Menu>

        <asp:WebPartZone
            id="WebPartZone1"
            CssClass="column"
            Runat="server">
            <ZoneTemplate>
                <user:FirstSimplePart
                    id="FirstSimplePart1"
                    Title="First Web Part"
                    Description="Our first simple Web Part"
                    Runat="server" />
                <user:SecondSimplePart
                    id="SecondSimplePart1"
                    Title="Second Web Part"
                    Description="Our second simple Web Part"
                    Runat="server" />
            </ZoneTemplate>
        </asp:WebPartZone>

        <asp:WebPartZone
            id="WebPartZone2"
            CssClass="column"
            Runat="server" />

        <asp:CatalogZone
            id="CatalogZone1"
            CssClass="column"
            Runat="server">
            <ZoneTemplate>
            <asp:PageCatalogPart
                id="PageCatalogPart1"
                Runat="server" />
            </ZoneTemplate>
        </asp:CatalogZone>

    </form>
</body>
</html>

After you open the page in Listing 27.11, you see two Web Parts in the left column Web Part Zone. You can close either Web Part by selecting Close from the Web Part’s menu. If you click the Catalog link, you can open the Page Catalog and add any closed Web Parts back to the page (see Figure 27.8).

Adding closed Web Parts from the Page Catalog.

Figure 27.8. Adding closed Web Parts from the Page Catalog.

Note

You can prevent users from closing Web Parts by setting the CloseVerb-Visible property on a WebPartZone control to the value false.

Using the Import Catalog Part

If you need to transfer a Web Part control’s settings between two different pages, or even between two different applications, you can export the Web Part from one page and import the Web Part on another page.

When you export a Web Part, an XML file that represents the Web Part’s properties is generated. You can download and save the settings file to your local computer. After you export the settings file, you can import the settings to any Web Part application that includes an Import Catalog Part and knows about the type of Web Part control that you are importing. When you import a Web Part, a new instance of the Web Part control is created that contains the original settings.

Note

You can programmatically export and import Web Parts by using the WebPartManager control’s ExportWebPart() and ImportWebPart() methods.

Before you can export any Web Parts from a page, you must enable exporting for your application. The web configuration file in Listing 27.12 contains the necessary configuration settings.

Example 27.12. Web.Config

<?xml version="1.0"?>
<configuration>
    <system.web>
      <webParts enableExport="true" />
    </system.web>
 </configuration>

To make things more interesting, we’ll create a new Web Part to illustrate how exporting a Web Part works. The new Web Part represents a user profile. It displays both sensitive and non-sensitive data. The ProfilePart is contained in Listing 27.13.

Example 27.13. ProfilePart.ascx

<%@ Control Language="VB" ClassName="ProfilePart" %>

<script runat="server">
    Private _firstName As String
    Private _lastName As String
    Private _socialSecurityNumber As String
    Private _userProfile As String

    <Personalizable()> _
    <WebBrowsable()> _
    Public Property FirstName() As String
        Get
            Return _firstName
        End Get
        Set(ByVal Value As String)
            _firstName = value
        End Set
    End Property

    <Personalizable()> _
    <WebBrowsable()> _
    Public Property LastName() As String
        Get
            Return _lastName
        End Get
        Set(ByVal Value As String)
            _lastName = value
        End Set
    End Property

    <Personalizable(PersonalizationScope.User, True)> _
    <WebBrowsable()> _
    Public Property SocialSecurityNumber() As String
        Get
            Return _socialSecurityNumber
        End Get
        Set(ByVal Value As String)
            _socialSecurityNumber = value
        End Set
    End Property

    <Personalizable()> _
    <WebBrowsable()> _
    Public Property UserProfile() As String
        Get
            Return _userProfile
        End Get
        Set(ByVal Value As String)
            _userProfile = value
        End Set
    End Property

    Private Sub Page_PreRender()
        lblFirstName.Text = _firstName
        lblLastName.Text = _lastName
        lblSocialSecurityNumber.Text = _socialSecurityNumber
        lblUserProfile.Text = _userProfile
    End Sub

</script>
First Name:
<asp:Label
    id="lblFirstName"
    Runat="server" />
<br />
Last Name:
<asp:Label
    id="lblLastName"
    Runat="server" />
<br />
Social Security Number:
<asp:Label
    id="lblSocialSecurityNumber"
    Runat="server" />
<br />
User Profile:
<asp:Label
    id="lblUserProfile"
    Runat="server" />

The ProfilePart displays four profile properties: a person’s First Name, Last Name, Social Security Number, and User Profile. The value of the Social Security Number property is considered to be sensitive data and the values of the other properties are not.

Notice that all four properties in Listing 27.13 are decorated with the Personalizable attribute. Only properties marked with this attribute can be exported.

Furthermore, notice that the Personalizable attribute associated with the SocialSecurityNumber property includes two parameters. The second parameter represents whether or not the property contains sensitive data. To prevent the Social Security Number from being exported, this parameter is set to the value True.

The page in Listing 27.14 illustrates how you can use the ProfilePart in a page.

Example 27.14. ShowImportCatalogPart.aspx

<%@ Page Language="VB" %>
<%@ Register TagPrefix="user" TagName="ProfilePart" Src="~/ProfilePart.ascx" %>
<%@ Register TagPrefix="user" TagName="FirstSimplePart" Src="~/FirstSimplePart.ascx" %>
<%@ Register TagPrefix="user" TagName="SecondSimplePart" Src="~/SecondSimplePart.ascx" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<script runat="server">

    Sub Menu1_MenuItemClick(ByVal sender As Object, ByVal e As MenuEventArgs)
        WebPartManager1.DisplayMode = WebPartManager1.DisplayModes(e.Item.Text)
    End Sub
</script>

<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
    <style type="text/css">
        .column
        {
            float:left;
            width:30%;
            height:200px;
            margin-right:10px;
            border:solid 1px black;
            background-color: white;
        }
        .menu
        {
            margin:5px 0px;
        }
        html
        {
            background-color:#eeeeee;
        }
    </style>
    <title>Show Import Catalog Part</title>
</head>
<body>
    <form id="form1" runat="server">
    <asp:WebPartManager
        id="WebPartManager1"
        Runat="server" />

        <asp:Menu
            id="Menu1"
            OnMenuItemClick="Menu1_MenuItemClick"
            Orientation="Horizontal"
            CssClass="menu"
            Runat="server">
            <Items>
            <asp:MenuItem Text="Browse" />
            <asp:MenuItem Text="Design" />
            <asp:MenuItem Text="Catalog" />
            <asp:MenuItem Text="Edit" />
            </Items>
        </asp:Menu>

        <asp:WebPartZone
            id="WebPartZone1"
            CssClass="column"
            Runat="server">
            <ZoneTemplate>
                <user:ProfilePart
                    id="ProfilePart1"
                    Title="Profile Part"
                    Description="Displays your profile"
                    ExportMode="NonSensitiveData"
                    Runat="server" />
                <user:FirstSimplePart
                    id="FirstSimplePart1"
                    Title="First Web Part"
                    Description="Our first simple Web Part"
                    Runat="server" />
                <user:SecondSimplePart
                    id="SecondSimplePart1"
                    Title="Second Web Part"
                    Description="Our second simple Web Part"
                    Runat="server" />
            </ZoneTemplate>
        </asp:WebPartZone>

        <asp:WebPartZone
            id="WebPartZone2"
            CssClass="column"
            Runat="server" />

        <asp:CatalogZone
            id="CatalogZone1"
            CssClass="column"
            Runat="server">
            <ZoneTemplate>
            <asp:ImportCatalogPart
                id="ImportCatalogPart1"
                Runat="server" />
            </ZoneTemplate>
        </asp:CatalogZone>

        <asp:EditorZone
            id="EditorZone1"
            CssClass="column"
            Runat="server">
            <ZoneTemplate>
            <asp:PropertyGridEditorPart
                id="PropertyGridEditorPart1"
                Runat="server" />
            </ZoneTemplate>
        </asp:EditorZone>

    </form>
</body>
</html>

In Listing 27.14, the ProfilePart is declared in the first Web Part Zone. Notice that the ProfilePart includes an ExportMode property. This property can have three possible values:

  • NoneThe default value is to prevent users from exporting a Web Part.

  • AllThis value enables users to export both sensitive and non-sensitive data.

  • NonSensitiveDataThis value enables users to export only data that has not been marked as sensitive.

The first thing that you should do after opening the page in Listing 27.14 is to create a user profile. Click the Edit link to switch the page to Edit Display Mode. Select the Edit menu option on the ProfilePart and enter values for the ProfilePart control’s properties. Click the OK button when you are finished.

Next, you can export the ProfilePart by selecting Export from the ProfilePart control’s menu (see Figure 27.9). When you export the ProfilePart, an XML file resembling the file in Listing 27.15 is downloaded to your computer.

Exporting a Web Part.

Figure 27.9. Exporting a Web Part.

Example 27.15. ProfilePart.WebPart

<?xml version="1.0" encoding="utf-8"?>
<webParts>
  <webPart>
    <metaData>
      <type src="~/ProfilePart.ascx" />
      <importErrorMessage>Cannot import this Web Part.</importErrorMessage>
    </metaData>
    <data>
      <properties>
        <property name="LastName" type="string">Walther</property>
        <property name="FirstName" type="string">Ruth</property>
        <property name="UserProfile" type="string">I like ASP.NET 2.0!</property>
      </properties>
      <genericWebPartProperties>
        <property name="AllowClose" type="bool">True</property>
        <property name="Width" type="unit" />
        <property name="AllowMinimize" type="bool">True</property>
        <property name="AllowConnect" type="bool">True</property>
        <property name="ChromeType" type="chrometype">Default</property>
        <property name="TitleIconImageUrl" type="string" />
        <property name="Description" type="string">Displays your profile</property>
        <property name="Hidden" type="bool">False</property>
        <property name="TitleUrl" type="string" />
        <property name="AllowEdit" type="bool">True</property>
        <property name="Height" type="unit" />
        <property name="HelpUrl" type="string" />
        <property name="Title" type="string">Profile Part</property>
        <property name="CatalogIconImageUrl" type="string" />
        <property name="Direction" type="direction">NotSet</property>
        <property name="ChromeState" type="chromestate">Normal</property>
        <property name="AllowZoneChange" type="bool">True</property>
        <property name="AllowHide" type="bool">True</property>
        <property name="HelpMode" type="helpmode">Navigate</property>
        <property name="ExportMode" type="exportmode">NonSensitiveData</property>
      </genericWebPartProperties>
    </data>
  </webPart>
 </webParts>

Notice that the file in Listing 27.15 does not include the Social Security Number property. However, it does include the First Name, Last Name, and User Profile properties.

After you download the XML file, you can import the Web Part represented by the XML file into another Web Part page or another Web Part application. Click the Catalog link to switch to Catalog Display Mode. The Import Catalog Part enables you to upload a Web Part settings file.

After you upload the settings file, the Web Part represented by the file is listed by the Import Catalog Part. You can add the ProfilePart to any Web Part Zone (see Figure 27.10).

Importing a Web Part.

Figure 27.10. Importing a Web Part.

Using Editor Zones

You use an Editor Zone to enable users to edit the Web Parts contained in a page. An Editor Zone can contain one or more Editor Parts. The contents of an Editor Zone are displayed only when the page is in Edit Display Mode.

The Web Part Framework includes four standard Editor Parts: the AppearanceEditorPart, the BehaviorEditorPart, the LayoutEditorPart, and the PropertyGridEditorPart. This section discusses each of these Editor Parts.

Note

You can create your own Editor Parts. This option is explored in Chapter 30, “Extending the Web Part Framework.”

Using the Appearance Editor Part

The AppearanceEditorPart control is useful for an administrator of a Web Part application, who can use the part to modify the general appearances of the Web Parts in the application (see Figure 27.11). This control enables you to modify the following properties of a Web Part:

  • TitleThe title displayed for a Web Part in the Web Part title bar.

  • ChromeTypeThe type of chrome rendered around a Web Part. Possible values are Default, TitleAndBorder, TitleOnly, BorderOnly, and None.

  • DirectionThe direction that text is displayed in a Web Part. This property is useful when working with languages that are written from right to left, such as Arabic.

  • HeightThe pixel height of the Web Part.

  • WidthThe pixel width of the Web Part.

  • HiddenWhen true, the Web Part is not displayed in a browser. The Web Part is rendered with a display:hidden Cascading Style Sheet property.

Using the AppearanceEditorPart.

Figure 27.11. Using the AppearanceEditorPart.

The page in Listing 27.16 illustrates how you can add the AppearanceEditorPart to an Editor Zone.

Example 27.16. ShowAppearanceEditorPart.aspx

<%@ Page Language="VB" %>
<%@ Register TagPrefix="user" TagName="FirstSimplePart" Src="~/FirstSimplePart.ascx" %>
<%@ Register TagPrefix="user" TagName="SecondSimplePart" Src="~/SecondSimplePart.ascx" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<script runat="server">

    Sub Menu1_MenuItemClick(ByVal sender As Object, ByVal e As MenuEventArgs)
        WebPartManager1.DisplayMode = WebPartManager1.DisplayModes(e.Item.Text)
    End Sub
</script>

<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
    <style type="text/css">
        .column
        {
            float:left;
            width:30%;
            height:200px;
            margin-right:10px;
            border:solid 1px black;
            background-color: white;
        }
        .menu
        {
            margin:5px 0px;
        }
        html
        {
            background-color:#eeeeee;
        }
    </style>
    <title>Show Appearance Editor Part</title>
</head>
<body>
    <form id="form1" runat="server">
    <asp:WebPartManager
        id="WebPartManager1"
        Runat="server" />

        <asp:Menu
            id="Menu1"
            OnMenuItemClick="Menu1_MenuItemClick"
            Orientation="Horizontal"
            CssClass="menu"
            Runat="server">
            <Items>
            <asp:MenuItem Text="Browse" />
            <asp:MenuItem Text="Design" />
            <asp:MenuItem Text="Edit" />
            </Items>
        </asp:Menu>

        <asp:WebPartZone
            id="WebPartZone1"
            CssClass="column"
            Runat="server">
            <ZoneTemplate>
                <user:FirstSimplePart
                    id="FirstSimplePart1"
                    Title="First Web Part"
                    Description="Our first simple Web Part"
                    Runat="server" />
                <user:SecondSimplePart
                    id="SecondSimplePart1"
                    Title="Second Web Part"
                    Description="Our second simple Web Part"
                    Runat="server" />
            </ZoneTemplate>
        </asp:WebPartZone>

        <asp:WebPartZone
            id="WebPartZone2"
            CssClass="column"
            Runat="server" />

        <asp:EditorZone
            id="EditorZone1"
            CssClass="column"
            Runat="server">
            <ZoneTemplate>
            <asp:AppearanceEditorPart
                id="AppearanceEditorPart1"
                Runat="server" />
            </ZoneTemplate>
        </asp:EditorZone>

    </form>
</body>
</html>

After you open the page in Listing 27.16, you can view the Appearance Editor Part by clicking the page menu’s Edit link, and then selecting Edit from either of the two Web Part control menus.

Using the Behavior Editor Part

The Behavior Editor Part can be used to modify properties of a Web Part that have Shared personalization scope. In other words, it can be used to modify the properties that appear for all users and not only the current user.

The Behavior Editor Part enables you to modify the following properties:

  • DescriptionEnables you to set the Web Part description that appears as a tooltip when you hover your mouse over a Web Part.

  • Title LinkEnables you to convert the title of a Web Part into a hyperlink to a page.

  • Title Icon Image LinkEnables you to specify an image that appears in a Web Part title bar.

  • Catalog Icon Image LinkEnables you to specify an image that appears when a Web Part is listed in a Catalog Part.

  • Help LinkEnables you to add a Help menu item that links to a help page.

  • Help ModeEnables you to specify how the help window appears when you select a Web Part’s Help menu option. Possible values are Modal, Modeless, and Navigate.

  • Import Error MessageEnables you to specify the error text that appears when a Web Part is imported with an ImportCatalogPart control that fails.

  • Export ModeEnables you to specify whether a Web Part can be exported. Possible values are Do Not Allow, Export All Values, and Non-Sensitive Data Only.

  • Authorization FilterEnables you to specify a string that can be used to determine whether a Web Part can be added to a page.

  • Allow CloseEnables you to prevent users from closing a Web Part.

  • Allow ConnectEnables you to specify whether a user is allowed to connect the current Web Part to another Web Part.

  • Allow EditEnables you to specify whether a Web Part can be edited.

  • Allow HideEnables you to specify whether a user can hide a Web Part (render the Web Part, but not display it).

  • Allow MinimizeEnables you to specify whether a user is allowed to minimize a Web Part.

  • Allow Zone ChangeEnables you to specify whether a user is allowed to drag and drop the Web Part to a new location.

The Behavior Editor Part appears only when Shared personalization scope has been enabled for the page. You’ll learn the gritty details of Shared personalization scope in Chapter 29, “Personalizing Web Parts.” Right now, however, it is enough to know that there are two requirements for placing a page into Shared personalization scope.

First, you need to add the web configuration file in Listing 27.17 to your application.

Example 27.17. Web.Config

<?xml version="1.0"?>
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
    <system.web>
      <webParts>
        <personalization>
          <authorization>
            <allow users="*" verbs="enterSharedScope"/>
          </authorization>
        </personalization>
      </webParts>
    </system.web>
 </configuration>

The Web Configuration file in Listing 27.17 authorizes all users to enter Shared personalization scope (the asterisk represents everyone). Normally, you want to restrict this privilege to the administrators of your application.

Next, you need to place the current page in Shared personalization scope. One way to do this is to use the Personalization property of the WebPartManager control, like this:

<asp:WebPartManager
    id="WebPartManager1"
    Personalization-InitialScope="Shared"
    Runat="server" />

The Personalization-InitialScope attribute causes the page to enter Shared personalization scope for users who are authorized by the web configuration file to enter Shared personalization scope. If a user is not authorized, the attribute is ignored.

The page in Listing 27.18 illustrates how you can add a BehaviorEditorPart control to an EditorZone.

Example 27.18. ShowBehaviorEditorPart.aspx

<%@ Page Language="VB" %>
<%@ Register TagPrefix="user" TagName="FirstSimplePart" Src="~/FirstSimplePart.ascx" %>
<%@ Register TagPrefix="user" TagName="SecondSimplePart" Src="~/SecondSimplePart.ascx" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<script runat="server">

    Sub Menu1_MenuItemClick(ByVal sender As Object, ByVal e As MenuEventArgs)
        WebPartManager1.DisplayMode = WebPartManager1.DisplayModes(e.Item.Text)
    End Sub
</script>

<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
    <style type="text/css">
        .column
        {
            float:left;
            width:30%;
            height:200px;
            margin-right:10px;
            border:solid 1px black;
            background-color: white;
        }
        .menu
        {
            margin:5px 0px;
        }
        html
        {
            background-color:#eeeeee;
        }
    </style>
    <title>Show Behavior Editor Part</title>
</head>
<body>
    <form id="form1" runat="server">
    <asp:WebPartManager
        id="WebPartManager1"
        Personalization-InitialScope="Shared"
        Runat="server" />

        <asp:Menu
            id="Menu1"
            OnMenuItemClick="Menu1_MenuItemClick"
            Orientation="Horizontal"
            CssClass="menu"
            Runat="server">
            <Items>
            <asp:MenuItem Text="Browse" />
            <asp:MenuItem Text="Design" />
            <asp:MenuItem Text="Edit" />
            </Items>
        </asp:Menu>

        <asp:WebPartZone
            id="WebPartZone1"
            CssClass="column"
            Runat="server">
            <ZoneTemplate>
                <user:FirstSimplePart
                    id="FirstSimplePart1"
                    Title="First Web Part"
                    Description="Our first simple Web Part"
                    Runat="server" />
                <user:SecondSimplePart
                    id="SecondSimplePart1"
                    Title="Second Web Part"
                    Description="Our second simple Web Part"
                    Runat="server" />
            </ZoneTemplate>
        </asp:WebPartZone>

        <asp:WebPartZone
            id="WebPartZone2"
            CssClass="column"
            Runat="server" />

        <asp:EditorZone
            id="EditorZone1"
            CssClass="column"
            Runat="server">
            <ZoneTemplate>
            <asp:BehaviorEditorPart
                id="BehaviorEditorPart1"
                Runat="server" />
            </ZoneTemplate>
        </asp:EditorZone>

    </form>
</body>
</html>

After you open the page in Listing 27.18 in your web browser, you can click the Edit menu link to place the page in Edit Display Mode. Next, select the Edit menu option on one of the two Web Parts, which causes the Behavior Editor Part to appear (see Figure 27.12).

Using the Behavior Editor Part.

Figure 27.12. Using the Behavior Editor Part.

Using the Layout Editor Part

The Layout Editor Part enables you to arrange Web Parts on a page without using a mouse (see Figure 27.13). You should always include a Layout Editor Part in every Web Parts page for two reasons.

Using the Layout Editor Part.

Figure 27.13. Using the Layout Editor Part.

First, adding a Layout Editor Part to a page makes your web application more accessible to persons with disabilities. Many persons with disabilities must interact with websites by using the keyboard. For example, if you are blind, then you will not be using a mouse to drag Web Parts around a page.

Web Standards Note

Both the Section 508 and WCAG 1.0 standards include guidelines concerned with the importance of creating device-independent pages.

Second, the Web Part Framework does not support drag-and-drop for browseers other than Internet Explorer. In particular, you cannot drag-and-drop Web parts when using Firefox or Opera. The Layout Editor Part provides you with an (imperfect) method of supporting browseres other than Internet Explorer.

The LayoutEditorPart control enables users to modify the following three properties:

  • Chrome StateEnables users to specify whether a Web Part is minimized or maximized.

  • ZoneEnables users to select a zone where they want a Web Part to be placed.

  • Zone IndexEnables users to specify the location of a Web Part within a zone.

The page in Listing 27.19 illustrates how you can add a LayoutEditorPart control to an Editor Zone.

Example 27.19. ShowLayoutEditorPart.aspx

<%@ Page Language="VB" %>
<%@ Register TagPrefix="user" TagName="FirstSimplePart" Src="~/FirstSimplePart.ascx" %>
<%@ Register TagPrefix="user" TagName="SecondSimplePart" Src="~/SecondSimplePart.ascx" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<script runat="server">

    Sub Menu1_MenuItemClick(ByVal sender As Object, ByVal e As MenuEventArgs)
        WebPartManager1.DisplayMode = WebPartManager1.DisplayModes(e.Item.Text)
    End Sub
</script>

<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
    <style type="text/css">
        .column
        {
            float:left;
            width:30%;
            height:200px;
            margin-right:10px;
            border:solid 1px black;
            background-color: white;
        }
        .menu
        {
            margin:5px 0px;
        }
        html
        {
            background-color:#eeeeee;
        }
    </style>
    <title>Show Layout Editor Part</title>
</head>
<body>
    <form id="form1" runat="server">
    <asp:WebPartManager
        id="WebPartManager1"
        Runat="server" />

        <asp:Menu
            id="Menu1"
            OnMenuItemClick="Menu1_MenuItemClick"
            Orientation="Horizontal"
            CssClass="menu"
            Runat="server">
            <Items>
            <asp:MenuItem Text="Browse" />
            <asp:MenuItem Text="Design" />
            <asp:MenuItem Text="Edit" />
            </Items>
        </asp:Menu>

        <asp:WebPartZone
            id="WebPartZone1"
            CssClass="column"
            Runat="server">
            <ZoneTemplate>
            <user:FirstSimplePart
                id="FirstSimplePart1"
                Title="First Web Part"
                Description="Our first simple Web Part"
                Runat="server" />
            <user:SecondSimplePart
                id="SecondSimplePart1"
                Title="Second Web Part"
                Description="Our second simple Web Part"
                Runat="server" />
            </ZoneTemplate>
        </asp:WebPartZone>

        <asp:WebPartZone
            id="WebPartZone2"
            CssClass="column"
            Runat="server" />

        <asp:EditorZone
            id="EditorZone1"
            CssClass="column"
            Runat="server">
            <ZoneTemplate>
            <asp:LayoutEditorPart
                id="LayoutEditorPart1"
                Runat="server" />
            </ZoneTemplate>
        </asp:EditorZone>

    </form>
</body>
</html>

When you open the page in Listing 27.19 in a web browser, you can click the Edit link to place the page into Edit Display Mode. Next, select the Edit menu option from any Web Part menu to see the Layout Editor Part.

Using the Property Grid Editor

The PropertyGridEditorPart control enables users to modify custom properties of a Web Part control through a form interface. This control automatically generates a property sheet for a Web Part (see Figure 27.14).

Using the Property Grid Editor Part.

Figure 27.14. Using the Property Grid Editor Part.

If you want to be able to modify a particular Web Part property with the PropertyGridEditorPart, then you must decorate the property with two attributes. First, you must add a Personalizable attribute to the property. The Web Part Framework automatically saves any property decorated with the Personalizable attribute.

Second, you must add a WebBrowsable attribute to the property. The WebBrowsable attribute is for the benefit of the PropertyGridEditorPart control. The control displays only properties decorated with this attribute.

The Web Part in Listing 27.20, the FeaturedMoviePart illustrates how to use both of these attributes.

Example 27.20. FeaturedMoviePart.ascx

<%@ Control Language="VB" ClassName="FeaturedMoviePart" %>

<script runat="server">

    Public Enum MovieCategory
        Action
        Animation
        Drama
        Horror
    End Enum

    Private _movieTitle As String
    Private _category As MovieCategory
    Private _movieDescription As String
    Private _inTheaters As Boolean

    <Personalizable()> _
    <WebBrowsable()> _
    <WebDisplayName("Title")> _
    <WebDescription("The title of the movie")> _
    Public Property MovieTitle() As String
        Get
            Return _movieTitle
        End Get
        Set(ByVal Value As String)
            _movieTitle = value
        End Set
    End Property

    <Personalizable()> _
    <WebBrowsable()> _
    <WebDisplayName("Category")> _
    <WebDescription("The movie category")> _
    Public Property Category() As MovieCategory
        Get
            Return _category
        End Get
        Set(ByVal Value As MovieCategory)
            _category = value
        End Set
    End Property

    <Personalizable()> _
    <WebBrowsable()> _
    <WebDisplayName("Description")> _
    <WebDescription("The movie description")> _
    Public Property MovieDescription() As String
        Get
            Return _movieDescription
        End Get
        Set(ByVal Value As String)
            _movieDescription = value
        End Set
    End Property

    <Personalizable()> _
    <WebBrowsable()> _
    <WebDisplayName("In Theaters")> _
    <WebDescription("Is the movie currently showing?")> _
    Public Property InTheaters() As Boolean
        Get
            Return _inTheaters
        End Get
        Set(ByVal Value As Boolean)
            _inTheaters = value
        End Set
    End Property

    Private Sub Page_PreRender()
        lblMovieTitle.Text = _movieTitle
        lblCategory.Text = _category.ToString()
        lblMovieDescription.Text = _movieDescription
        lblInTheaters.Visible = _inTheaters
    End Sub
</script>
<asp:Label
    id="lblMovieTitle"
    Runat="server" />
<br />
<asp:Label
    id="lblCategory"
    Runat="server" />
<br />
<asp:Label
    id="lblMovieDescription"
    Runat="server" />
<br />
<asp:Label
    id="lblInTheaters"
    Text="In Theaters Now!"
    CssClass="inTheaters"
    Runat="server" />

Notice that each of the properties of the FeatureMoviePart in Listing 27.20 is marked with four attributes. Each property includes the required Personalizable and WebBrowsable attributes. In addition, the WebDisplayName and WebDescription attributes are used to provide each property with a name and description in the property sheet.

The page in Listing 27.21 demonstrates how you can use the PropertyGridEditorPart control to edit the properties of the FeaturedMoviePart.

Example 27.21. ShowPropertyGridEditorPart.aspx

<%@ Page Language="VB" %>
<%@ Register TagPrefix="user" TagName="FeaturedMoviePart" Src="~/FeaturedMoviePart.ascx" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<script runat="server">

    Sub Menu1_MenuItemClick(ByVal sender As Object, ByVal e As MenuEventArgs)
        WebPartManager1.DisplayMode = WebPartManager1.DisplayModes(e.Item.Text)
    End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
    <style type="text/css">
        .column
        {
            float:left;
            width:30%;
            height:200px;
            margin-right:10px;
            border:solid 1px black;
            background-color: white;
        }
        .menu
        {
            margin:5px 0px;
        }
        html
        {
            background-color:#eeeeee;
        }
    </style>
    <title>Show Property Grid Editor Part</title>
</head>
<body>
    <form id="form1" runat="server">
    <asp:WebPartManager
        id="WebPartManager1"
        Runat="server" />

        <asp:Menu
            id="Menu1"
            OnMenuItemClick="Menu1_MenuItemClick"
            Orientation="Horizontal"
            CssClass="menu"
            Runat="server">
            <Items>
            <asp:MenuItem Text="Browse" />
            <asp:MenuItem Text="Design" />
            <asp:MenuItem Text="Edit" />
            </Items>
        </asp:Menu>

        <asp:WebPartZone
            id="WebPartZone1"
            CssClass="column"
            Runat="server">
            <ZoneTemplate>
                <user:FeaturedMoviePart
                    id="FeaturedMoviePart1"
                    Title="Featured Movie Part"
                    Description="Displays movie information"
                    Runat="server" />
            </ZoneTemplate>
        </asp:WebPartZone>

        <asp:WebPartZone
            id="WebPartZone2"
            CssClass="column"
            Runat="server" />

        <asp:EditorZone
            id="EditorZone1"
            CssClass="column"
            Runat="server">
            <ZoneTemplate>
            <asp:PropertyGridEditorPart
                id="PropertyGridEditorPart1"
                Runat="server" />
            </ZoneTemplate>
        </asp:EditorZone>
    </form>
</body>
</html>

After you open the page in Listing 27.21, you can click the Edit link to switch the page to Edit Display Mode. Next, select the Edit menu option on the FeaturedMoviePart and you will see the property sheet rendered by the PropertyGridEditorPart.

The PropertyGridEditorPart automatically associates certain types of properties with certain types of form fields in the property sheet:

  • Boolean Property—Displayed with a CheckBox control.

  • Enumeration Property—Displayed with a DropDownList control.

  • Other Properties—Displayed with a TextBox control.

In the case of the FeaturedMoviePart, The PropertyGridEditorPart control renders a TextBox control for the MovieTitle property, a DropDownList control for the Category property, a TextBox for the Description property, and a CheckBox control for the InTheaters property.

Note

The PropertyGridEditorPart does not provide you with very much control over the appearance of the property sheet. For example, there is no way to specify the order of the form fields. If you want more control, then you need to create a custom EditorPart. This option in discussed Chapter 30, “Extending the Web Part Framework.”

Using Connections Zones

You can share information between two or more Web Parts on a page by connecting the Web Parts. There are a variety of different situations in which you might want to communicate information between two Web Parts.

For example, imagine that you are creating a Web Part application for a human resources department. You could create one Web Part that enables you to select a current employee. Another Web Part might display insurance information for the selected employee. Yet another Web Part might display information about the selected employee’s work history. If you connect all the Web Parts, then you can select a new employee from the first Web Part to see detailed information about the employee with the other two Web Parts.

Or, imagine that you are building a blog application with Web Parts. One Web Part might display a calendar. A second Web Part might display a list of blog entries. If you connect the two Web Parts, you can select a date in the calendar Web Part to see a list of matching entries in the blog Web Part.

Connecting Web Parts

When you connect two Web Parts, you create a connection between a provider Web Part and a consumer Web Part. The provider Web Part provides the information that is retrieved by the consumer Web Part. Multiple consumer Web Parts can be connected to the same provider.

You must follow a certain sequence of steps whenever you connect two Web Parts:

  1. Create an interface that represents the information being shared.

  2. Add the ConnectionProvider attribute to a method of the provider Web Part.

  3. Add the ConnectionConsumer attribute to a method of the consumer Web Part.

Before you can communicate information between two Web Parts, you must specify an interface that describes the information being shared. An interface can contain a list of properties, methods, and events.

Next, the provider Web Part must have a method that returns a class that implements the interface. You mark the method that provides the interface by decorating the method with the ConnectionProvider attribute.

Finally, the consumer Web Part must have a method that retrieves the interface. This method is marked in the consumer Web Part with the ConnectionConsumer attribute.

Connecting Simple Web Parts

Let’s go ahead and build a simple provider and consumer Web Part that you can connect. The provider Web Part will enable users to enter a ZIP code. The consumer Web Part displays the weather for the selected ZIP code (see Figure 27.15).

Connecting the ZIP Code with the weather.

Figure 27.15. Connecting the ZIP Code with the weather.

First, you need to create an interface which describes the information being passed between the provider and consumer Web Parts. Our interface is contained in Listing 27.22.

Example 27.22. App_CodeIZIPCode.vb

''' <summary>
''' Represents a ZIP Code
''' </summary>
Public Interface IZIPCode
    ReadOnly Property ZIPCode() As String
 End Interface

The IZIPCode interface defines one read-only property named ZIPCode. This is the bit of information that will pass between the two Web Parts.

Note

The IZIPCode interface must be saved in the App_Code folder or it will not be automatically compiled.

Next, you need to create the provider Web Part. This Web Part enables a user to enter a ZIP code in a text box. The ZIPCodePart is contained in Listing 27.23.

Example 27.23. ZIPCodePart.ascx

<%@ Control Language="VB" ClassName="ZIPCodePart" %>
<%@ Implements Interface="IZIPCode" %>
<script runat="server">

    ''' <summary>
    ''' Implements the IZIPCode interface
    ''' </summary>
    Public ReadOnly Property ZIPCode() As String Implements IZIPCode.ZIPCode
        Get
            Return txtZIPCode.Text
        End Get
    End Property

    ''' <summary>
    ''' This method is called from connected Web Parts
    ''' </summary>
    <ConnectionProvider("ZIP Code")> _
    Public Function ProvideZIPCode() As IZIPCode
        Return Me
    End Function
</script>

<asp:Label
    id="lblZIPCode"
    AssociatedControlID="txtZIPCode"
    Text="ZIP Code:"
    Runat="server" />
<asp:TextBox
    id="txtZIPCode"
    Runat="server" />
<asp:Button
    id="btnSubmit"
    Text="Submit"
    Runat="server" />

Notice that the ZIPCodePart includes a method named ProvideZIPCode(), which is decorated with the ConnectionProvider attribute. This method is called by any consumer Web Parts connected to the ZIPCodePart.

The ProvideZIPCode() method returns the ZIPCodePart itself when the method is called. Notice that the ZIPCodePart implements the IZIPCode interface. The Web Part includes an <%@ Implements %> directive and it implements the ZIPCode property.

The provider Web Part is not required to implement the interface it exposes. If you prefer, you could return a different class that implements the IZIPCode interface from the ProvideZIPCode() method.

Now you are ready to create the consumer Web Part. This Web Part, named WeatherPart, displays the current weather. The code for the WeatherPart is contained in Listing 27.24.

Example 27.24. WeatherPart.ascx

<%@ Control Language="VB" ClassName="WeatherPart" %>
<script runat="server">

    Private _zipCode As IZIPCode

    ''' <summary>
    ''' This method retrieves the IZIPCode interface returned
    ''' by the ProvideZIPCode method
    ''' </summary>
    <ConnectionConsumer("ZIP Code")> _
    Public  Sub ConsumeZIPCode(ByVal zipCode As IZIPCode)
        _zipCode = zipCode
    End Sub


    ''' <summary>
    ''' Display the weather
    ''' </summary>
    Private  Sub Page_PreRender()
        ' Check if we are connected
        If Not _zipCode Is Nothing Then
            If _zipCode.ZIPCode <> String.Empty Then
                lblWeather.Text = String.Format("The weather for {0} is expected to be sunny!", _zipCode.ZIPCode)
            Else
                lblWeather.Text = "Please enter your ZIP code"
            End If
        End If
    End Sub

</script>

<h3>Current Weather</h3>
<asp:Label
    id="lblWeather"
    Runat="server" />

The WeatherPart contains a method named ConsumeZIPCode() that is decorated with the ConnectionConsumer attribute. This method is called when a class that implements the IZIPCode interface is returned from the provider Web Part.

The ConsumeZIPCode() method assigns the class that implements the IZIPCode interface to a private field. The private field is used to display the weather in the Page_PreRender() method.

Note

When working with connected Web Parts, it is important to know when in the page execution lifecycle the consumer Web Part actually calls the provider Web Part. This happens during the Page’s LoadComplete event, which occurs right after the Page’s Load event.

For this reason, the information exposed by a provider Web Part is not available during a consumer Web Part’s Load event. You should place all your logic that depends on this information in the Web Part’s PreRender event handler.

Finally, you can create a Web Part page that hosts the ZIPCodePart and WeatherPart. This page is contained in Listing 27.25.

Example 27.25. ConnectedSimpleParts.aspx

<%@ Page Language="VB" %>
<%@ Register TagPrefix="user" TagName="ZIPCodePart" Src="~/ZIPCodePart.ascx" %>
<%@ Register TagPrefix="user" TagName="WeatherPart" Src="~/WeatherPart.ascx" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<script runat="server">

    Sub Menu1_MenuItemClick(ByVal sender As Object, ByVal e As MenuEventArgs)
        WebPartManager1.DisplayMode = WebPartManager1.DisplayModes(e.Item.Text)
    End Sub
</script>

<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
    <style type="text/css">
        .column
        {
            float:left;
            width:40%;
            height:200px;
            margin-right:10px;
            border:solid 1px black;
            background-color: white;
        }
        .menu
        {
            margin:5px 0px;
        }
        html
        {
            background-color:#eeeeee;
        }
    </style>
    <title>Connected Simple Parts</title>
</head>
<body>
    <form id="form1" runat="server">
    <asp:WebPartManager
        id="WebPartManager1"
        Runat="server">
        <StaticConnections>
        <asp:WebPartConnection
            ID="WebPartConnection1"
            ProviderID="ZIPCodePart1"
            ConsumerID="WeatherPart1" />
        </StaticConnections>
     </asp:WebPartManager>

        <asp:Menu
            id="Menu1"
            OnMenuItemClick="Menu1_MenuItemClick"
            Orientation="Horizontal"
            CssClass="menu"
            Runat="server">
            <Items>
            <asp:MenuItem Text="Browse" />
            <asp:MenuItem Text="Design" />
            </Items>
        </asp:Menu>

        <asp:WebPartZone
            id="WebPartZone1"
            CssClass="column"
            Runat="server">
            <ZoneTemplate>
            <user:ZIPCodePart
                id="ZIPCodePart1"
                Title="ZIP Code Part"
                Description="Enables entry of ZIP code"
                Runat="Server" />
            </ZoneTemplate>
        </asp:WebPartZone>

        <asp:WebPartZone
            id="WebPartZone2"
            CssClass="column"
            Runat="server">
            <ZoneTemplate>
            <user:WeatherPart
                id="WeatherPart1"
                Title="Weather Part"
                Description="Displays current weather"
                Runat="Server" />
            </ZoneTemplate>
        </asp:WebPartZone>


    </form>
</body>
</html>

The page in Listing 27.25 contains the ZIPCodePart and WeatherPart in its two Web Part Zones. The two Web Parts are statically connected by the WebPartManager control. Notice that the WebPartManager control includes a <StaticConnections> section that connects the two parts.

After you open the page in Listing 27.25 in your web browser, you can enter a ZIP code in the ZIPCodePart and see the ZIP code displayed in the WeatherPart.

Note

If you place your WebPartManager control in a Master Page, you can still create static connections between Web Parts in a content page. To do this, you need to add a ProxyWebPartManager control that lists the static connections to the content page.

Connecting Databound Web Parts

This section tackles a slightly more complicated sample of connected Web Parts. You connect two Web Parts that display database data.

The provider Web Part displays a list of movie categories, and the consumer Web Part displays a list of movies. When the Web Parts are connected, you can select a movie category and see a list of matching movies (see Figure 27.16).

Connecting databound controls.

Figure 27.16. Connecting databound controls.

The first thing to do is define the interface that describes the information passed from the provider Web Part to the consumer Web Part. The interface is contained in Listing 27.26.

Example 27.26. IMovieCategory.vb

''' <summary>
''' Decribes the data exposed by
''' the MovieCategoryPart
''' </summary>
Public Interface IMovieCategory
    ReadOnly Property SelectedCategoryId() As Integer
 End Interface

The next step is to create the provider Web Part that exposes the IMovieCategory interface. The MovieCategoryPart is contained in Listing 27.27. This Web Part enables you to select a movie from a drop-down list.

Example 27.27. MovieCategoryPart.ascx

<%@ Control Language="VB" ClassName="MovieCategoryPart" %>
<%@ Implements Interface="IMovieCategory" %>

<script runat="server">
    ''' <summary>
    ''' Implements IMovieCategoryPart.SelectedCategoryId
    ''' </summary>
    Public ReadOnly Property SelectedCategoryId() As Integer Implements IMovieCategory.SelectedCategoryId
        Get
            Return CInt(dropCategories.SelectedValue)
        End Get
    End Property


    ''' <summary>
    ''' This method is called from connected Web Parts
    ''' </summary>
    <ConnectionProvider("Movie Category")> _
    Public Function ProvideCategory() As IMovieCategory
        Return Me
    End Function

</script>

<asp:Label
    id="lblCategory"
    Text="Movie Category:"
    AssociatedControlID="dropCategories"
    Runat="server" />

<asp:DropDownList
    id="dropCategories"
    DataSourceId="srcCategories"
    DataTextField="Name"
    DataValueField="Id"
    AutoPostBack="true"
    Runat="server" />

<asp:Button
    id="btnSelect"
    Text="Select"
    Runat="server" />

<asp:SqlDataSource
    id="srcCategories"
    ConnectionString="Server=.SQLExpress;
        Integrated Security=True;AttachDbFileName=|DataDirectory|MyDatabase.mdf;
        User Instance=True"
    SelectCommand="SELECT Id,Name FROM MovieCategories"
    Runat="server" />

The MovieCategoryPart contains a DropDownList control bound to a SqlDataSource control. The SqlDataSource control represents the contents of a SQL Express database table named MovieCategories.

Notice that the Web Part includes a method named ProvideCategory(), which is decorated with the ConnectionProvider attribute. This method returns a reference to the MovieCategoryPart when a consumer Web Part connects to the MovieCategoryPart.

The next step is to create the consumer Web Part. The consumer Web Part is named MovieListPart and it is contained in Listing 27.28.

Example 27.28. MovieListPart.ascx

<%@ Control Language="VB" ClassName="MovieListPart" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>

<script runat="server">

    Private _category As IMovieCategory

    ''' <summary>
    ''' This method is called when the ProvideCategory method
    ''' returns a class that implements the IMovieCategory interface
    ''' </summary>
    <ConnectionConsumer("Movie Category")> _
    Public  Sub ConsumeCategory(ByVal category As IMovieCategory)
        _category = category
    End Sub

    ''' <summary>
    ''' Update SelectedCategoryId from Provider Web Part
    ''' </summary>
    Private  Sub Page_PreRender()
        If Not _category Is Nothing Then
            srcMovies.SelectParameters("CategoryId").DefaultValue = _category.SelectedCategoryId.ToString()
        End If
    End Sub

</script>

<asp:GridView
    id="grdMovies"
    DataSourceId="srcMovies"
    Runat="server" />

<asp:SqlDataSource
    id="srcMovies"
    ConnectionString="Server=.SQLExpress;Integrated Security=True;
        AttachDbFileName=|DataDirectory|MyDatabase.mdf;User Instance=True"
    SelectCommand="SELECT Title,Director,YearReleased
        FROM Movies WHERE CategoryId=@CategoryId"
    Runat="server">
    <SelectParameters>
        <asp:Parameter Name="CategoryId" Type="int32" />
    </SelectParameters>
 </asp:SqlDataSource>

The MovieListPart displays a list of movies in a GridView control. When you connect the MovieListPart to the MovieCategoryPart, the MovieListPart displays only those movies that match the selected movie category.

Notice that the MovieListPart includes a method named ConsumeCategory(), which is decorated with the ConnectionConsumer attribute. This method retrieves the class that implements the IMovieCategory interface (the MovieCategoryPart) from the provider Web Part.

The Page_PreRender() method updates the list of movies displayed in the GridView control. The method updates the value of the CategoryId parameter used by the SqlDataSource control.

Finally, you can create a page that hosts the provider and consumer Web Parts. The page is contained in Listing 27.29.

Example 27.29. ConnectedDataParts.aspx

<%@ Page Language="VB" %>
<%@ Register TagPrefix="user" TagName="MovieCategoryPart" Src="~/MovieCategoryPart.ascx" %>
<%@ Register TagPrefix="user" TagName="MovieListPart" Src="~/MovieListPart.ascx" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<script runat="server">

    Sub Menu1_MenuItemClick(ByVal sender As Object, ByVal e As MenuEventArgs)
        WebPartManager1.DisplayMode = WebPartManager1.DisplayModes(e.Item.Text)
    End Sub

</script>

<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
    <style type="text/css">
        .column
        {
            float:left;
            width:45%;
            height:200px;
            margin-right:10px;
            border:solid 1px black;
            background-color: white;
        }
        .menu
        {
            margin:5px 0px;
        }
        html
        {
            background-color:#eeeeee;
        }
    </style>
    <title>Connected Data Parts</title>
</head>
<body>
    <form id="form1" runat="server">
    <asp:WebPartManager
        id="WebPartManager1"
        Runat="server">
        <StaticConnections>
        <asp:WebPartConnection
            ID="WebPartConnection1"
            ProviderID="MovieCategoryPart1"
            ConsumerID="MovieListPart1" />
        </StaticConnections>
     </asp:WebPartManager>

        <asp:Menu
            id="Menu1"
            OnMenuItemClick="Menu1_MenuItemClick"
            Orientation="Horizontal"
            CssClass="menu"
            Runat="server">
            <Items>
            <asp:MenuItem Text="Browse" />
            <asp:MenuItem Text="Design" />
            </Items>
        </asp:Menu>

        <asp:WebPartZone
            id="WebPartZone1"
            CssClass="column"
            Runat="server">
            <ZoneTemplate>
            <user:MovieCategoryPart
                id="MovieCategoryPart1"
                Title="Movie Category Part"
                Description="Displays movie categories"
                Runat="Server" />
            </ZoneTemplate>
        </asp:WebPartZone>

        <asp:WebPartZone
            id="WebPartZone2"
            CssClass="column"
            Runat="server">
            <ZoneTemplate>
            <user:MovieListPart
                id="MovieListPart1"
                Title="Movie List Part"
                Description="Displays list of movies"
                Runat="Server" />
            </ZoneTemplate>
        </asp:WebPartZone>


    </form>
</body>
</html>

The page in Listing 27.29 statically connects the MovieCategoryPart and MovieListPart Web Parts. The static connection is created in the WebPartManager control’s <StaticConnections> section.

Dynamically Connecting Web Parts

In the previous sections, you connected Web Parts by declaring a static connection between the Web Parts. Creating a static connection makes sense when the Web Parts themselves are also statically declared in the page.

There are situations, however, in which you will want to enable users of your application to form dynamic connections between Web Parts. For example, you might want to allow a user to add a new Web Part to a page from a catalog of Web Parts and connect the new Web Part to an existing Web Part.

You can enable users to create dynamic connections between Web Parts by adding a Connections Zone to a page. The page in Listing 27.30 illustrates how you can declare a Connections Zone.

Example 27.30. ConnectedDynamicParts.aspx

<%@ Page Language="VB" %>
<%@ Register TagPrefix="user" TagName="ZIPCodePart" Src="~/ZIPCodePart.ascx" %>
<%@ Register TagPrefix="user" TagName="WeatherPart" Src="~/WeatherPart.ascx" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<script runat="server">

    Sub Menu1_MenuItemClick(ByVal sender As Object, ByVal e As MenuEventArgs)
        WebPartManager1.DisplayMode = WebPartManager1.DisplayModes(e.Item.Text)
    End Sub
</script>

<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
    <style type="text/css">
        .column
        {
            float:left;
            width:30%;
            height:200px;
            margin-right:10px;
            border:solid 1px black;
            background-color: white;
        }
        .menu
        {
            margin:5px 0px;
        }
        html
        {
            background-color:#eeeeee;
        }
    </style>
    <title>Connected Dynamic Parts</title>
</head>
<body>
    <form id="form1" runat="server">
    <asp:WebPartManager
        id="WebPartManager1"
        Runat="server" />

        <asp:Menu
            id="Menu1"
            OnMenuItemClick="Menu1_MenuItemClick"
            Orientation="Horizontal"
            CssClass="menu"
            Runat="server">
            <Items>
            <asp:MenuItem Text="Browse" />
            <asp:MenuItem Text="Design" />
            <asp:MenuItem Text="Catalog" />
            <asp:MenuItem Text="Connect" />
            </Items>
        </asp:Menu>

        <asp:WebPartZone
            id="WebPartZone1"
            CssClass="column"
            Runat="server" />

        <asp:WebPartZone
            id="WebPartZone2"
            CssClass="column"
            Runat="server" />

        <asp:CatalogZone
            id="CatalogZone1"
            CssClass="column"
            Runat="server">
            <ZoneTemplate>
            <asp:DeclarativeCatalogPart
                id="DeclarativeCatalogPart1"
                Runat="server">
                <WebPartsTemplate>
                <user:ZIPCodePart
                    id="ZIPCodePart1"
                    Title="ZIP Code Part"
                    Description="Enables entry of ZIP code"
                    Runat="Server" />
                <user:WeatherPart
                    id="WeatherPart1"
                    Title="Weather Part"
                    Description="Displays current weather"
                    Runat="Server" />
                </WebPartsTemplate>
            </asp:DeclarativeCatalogPart>
            </ZoneTemplate>
        </asp:CatalogZone>

        <asp:ConnectionsZone
            id="ConnectionsZone"
            CssClass="column"
            Runat="server" />

    </form>
</body>
</html>

Notice that, unlike other tool zones, the Connections Zone does not include any parts. In Listing 27.30, a <ConnectionsZone> tag is declared in the page without any child elements.

If you open the page in Listing 27.30 in your browser, you can click the Catalog link to display the contents of the Declarative Catalog. Next, you can add an instance of both the ZIPCodePart and WeatherPart to the page. At this point, the two Web Parts are not connected.

Next, you can connect the Web Parts by clicking the Connect link and selecting Connect from either of the two Web Part control’s menus. For example, if you select Connect from the WeatherPart control’s menu and click the Create a Connection to a Provider link, the connection interface in Figure 27.17 appears.

Dynamically connecting two Web Parts.

Figure 27.17. Dynamically connecting two Web Parts.

You can select the ZIP Code Part from the drop-down list to connect the two Web Parts. After the Web Parts are connected, entering a ZIP code causes the Weather Part to display the weather for that ZIP code.

Using Transformers with Connected Web Parts

For two Web Parts to communicate, the two Web Parts must agree on a common interface. With careful planning, a single developer can build a set of Web Parts and interfaces that enable all the Web Parts contained in an application to communicate cleanly.

However, imagine that you need to connect Web Parts created by different developers in your organization. Or imagine that you need to connect Web Parts sold by different companies. It is unlikely that the Web Parts will share exactly the same interfaces.

In situations in which you do not have control over the interface exposed by a Web Part, you can take advantage of a Transformer to modify the interface. A Transformer enables you to transform the data passed between a provider Web Part and a consumer Web Part.

Imagine, for example, that you buy a new Web Part—named the LocalNewsPart—that displays a list of local news headlines. You want to use this new Web Part with your existing ZIPCodePart and WeatherPart in an application.

Unfortunately, you quickly discover that you cannot connect the LocalNewsPart to the ZIPCodePart control. The two Web Parts expect different interfaces. To solve this problem, you need to create a Transformer.

The LocalNewsPart Web Part is contained in Listing 27.31.

Example 27.31. LocalNewsPart.ascx

<%@ Control Language="VB" ClassName="LocalNewsPart" %>

<script runat="server">

    Private _zipCode As INewsZIPCode

    ''' <summary>
    ''' This method retrieves the INewsZIPCode interface returned
    ''' by the provider Web Part
    ''' </summary>
    <ConnectionConsumer("News ZIP Code")> _
    Public Sub ConsumeZIPCode(ByVal zipCode As INewsZIPCode)
        _zipCode = zipCode
    End Sub


    ''' <summary>
    ''' Display the news
    ''' </summary>
    Private  Sub Page_PreRender()
        ' Check if we are connected
        If Not _zipCode Is Nothing Then
            If _zipCode.ZIPCode <> String.Empty Then
                lblNews.Text = String.Format("Everything looks terrific for {0}!", _zipCode.ZIPCode)
            Else
                lblNews.Text = "Please enter your ZIP code"
            End If
        End If
    End Sub
</script>

<h3>Current News</h3>
<asp:Label
    id="lblNews"
    Runat="server" />

The LocalNewsPart Web Part uses the interface defined in Listing 27.32—the INewsZIPCode interface—to represent a ZIP code.

Example 27.32. App_CodeINewsZIPCode.vb

''' <summary>
''' Represents a ZIP code
''' </summary>
Public Interface INewsZIPCode
    ReadOnly Property ZIPCode() As String
 End Interface

The INewsZIPCode interface represents a ZIP code in exactly the same way as the IZIPCode interface used by the ZIPCodePart and WeatherPart Web Parts. Unfortunately, however, it is a different interface. Therefore, before you can connect the LocalNewsPart Web Part to the ZIPCodePart, you must first define a Transformer.

The Transformer in Listing 27.33 converts an instance of the IZIPCode interface to an instance of the INewsZIPCode interface.

Example 27.33. App_CodeIPCodeTransformer.vb

Imports System
Imports System.Web.UI.WebControls.WebParts

Namespace myControls

    ''' <summary>
    ''' This class transforms an IZIPCode to
    ''' an INewsZIPCode
    ''' </summary>
    <WebPartTransformer(GetType(IZIPCode), GetType(INewsZIPCode))> _
    Public Class ZIPCodeTransformer
        Inherits WebPartTransformer
        Public Overrides Function Transform(ByVal providerData As Object) As Object
            Return New TempZIP((CType(providerData, IZIPCode)).ZIPCode)
        End Function
    End Class

    Public Class TempZIP
        Implements INewsZIPCode
        Private _zipCode As String

        Public ReadOnly Property ZIPCode() As String Implements INewsZIPCode.ZIPCode
            Get
                Return _zipCode
            End Get
        End Property

        Friend Sub New(ByVal zipCode As String)
            _zipCode = zipCode
        End Sub
    End Class
 End Namespace

After you create the file in Listing 27.33, you need to add it to your application’s App_Code folder to automatically compile the Transformer class.

There are a number of things that you should notice about the code for the Transformer. First, notice that the ZIPCodeTransformer class is decorated with a WebPartTransformer attribute. This attribute has two parameters: the provider interface and the consumer interface.

Next, you should notice that the ZIPCodeTransformer class derives from the base WebPartTransformer class. The ZIPCodeTransformer class overrides the base class’s Transform() method. The Transform() method takes the instance of the interface provided by the provider Web Part and transforms it into an instance of an interface appropriate for the consumer Web Part.

Note

The WebPartTransformer class includes another useful method that you can override: the CreateConfigurationControl() method. You can use this method to return an editor for configuring a Transformer. The Transformer editor appears when you click the Edit button in the Connections Zone.

Before you can use a Transformer in an application, you must register the Transformer in your application’s web configuration file. The file in Listing 27.34 contains the necessary configuration settings.

Example 27.34. Web.Config

<?xml version="1.0"?>
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
    <system.web>
      <webParts>
        <transformers>
          <add
                name="ZIPCodeTransformer"
                type="myControls.ZIPCodeTransformer"/>
        </transformers>
      </webParts>
    </system.web>
</configuration>

After you are finished setting up the Transformer, you can use the Transformer when creating either a static or dynamic connection between Web Parts. The page in Listing 27.35 demonstrates how you can declare a Transformer when creating a static connection between the ZIPCodePart and the LocalNewsPart Web Parts.

Example 27.35. ConnectedTransformerParts.aspx

<%@ Page Language="VB" %>
<%@ Register TagPrefix="user" TagName="ZIPCodePart" Src="~/ZIPCodePart.ascx" %>
<%@ Register TagPrefix="user" TagName="WeatherPart" Src="~/WeatherPart.ascx" %>
<%@ Register TagPrefix="user" TagName="LocalNewsPart" Src="~/LocalNewsPart.ascx" %>
<%@ Register TagPrefix="custom" Namespace="myControls" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<script runat="server">

    Sub Menu1_MenuItemClick(ByVal sender As Object, ByVal e As MenuEventArgs)
        WebPartManager1.DisplayMode = WebPartManager1.DisplayModes(e.Item.Text)
    End Sub

</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
    <style type="text/css">
        .column
        {
            float:left;
            width:45%;
            height:200px;
            margin-right:10px;
            border:solid 1px black;
            background-color: white;
        }
        .menu
        {
            margin:5px 0px;
        }
        html
        {
            background-color:#eeeeee;
        }
    </style>
    <title>Connected Transformer Parts</title>
</head>
<body>
    <form id="form1" runat="server">
    <asp:WebPartManager
        id="WebPartManager1"
        Runat="server">
        <StaticConnections>
        <asp:WebPartConnection
            ID="WebPartConnection1"
            ProviderID="ZIPCodePart1"
            ConsumerID="WeatherPart1" />
        <asp:WebPartConnection
            ID="WebPartConnection2"
            ProviderID="ZIPCodePart1"
            ConsumerID="LocalNewsPart1">
            <custom:ZIPCodeTransformer
                Runat="Server" />
         </asp:WebPartConnection>
        </StaticConnections>
     </asp:WebPartManager>

        <asp:Menu
            id="Menu1"
            OnMenuItemClick="Menu1_MenuItemClick"
            Orientation="Horizontal"
            CssClass="menu"
            Runat="server">
            <Items>
            <asp:MenuItem Text="Browse" />
            <asp:MenuItem Text="Design" />
            </Items>
        </asp:Menu>

        <asp:WebPartZone
            id="WebPartZone1"
            CssClass="column"
            Runat="server">
            <ZoneTemplate>
            <user:ZIPCodePart
                id="ZIPCodePart1"
                Title="ZIP Code Part"
                Description="Enables entry of ZIP code"
                Runat="Server" />
            </ZoneTemplate>
        </asp:WebPartZone>

        <asp:WebPartZone
            id="WebPartZone2"
            CssClass="column"
            Runat="server">
            <ZoneTemplate>
            <user:WeatherPart
                id="WeatherPart1"
                Title="Weather Part"
                Description="Displays current weather"
                Runat="Server" />
            <user:LocalNewsPart
                id="LocalNewsPart1"
                Title="Local News Part"
                Description="Displays current news"
                Runat="Server" />
            </ZoneTemplate>
        </asp:WebPartZone>
    </form>
</body>
</html>

The ZIPCodeTransformer is registered at the top of the page in Listing 27.35. The page uses the ZIPCodeTransformer in the declaration of the static connection between the ZIPCodePart and the LocalNewsPart Web Parts.

After you configure a Transformer in an application’s web configuration file, you don’t need to do anything special to use the Transformer in a page in which you are dynamically connecting Web Parts.

For example, the page in Listing 27.35 contains a catalog that lists the ZIPCodePart, the WeatherPart, and the LocalNewsPart. You can add all three Web Parts to a page and then connect the Web Parts by clicking the Connect link and selecting the Connect menu option included in each Web Part menu. If you connect the LocalNewsPart to the ZIPCodePart, the connection will automatically use the ZIPCodeTransformer.

Summary

This chapter introduced you to the Web Part Framework. You learned how to use each of the different types of zones that you can add to a Web Part page.

You learned how to use Web Part Zones to mark the areas in a page that can contain Web Parts. You also saw how you can take advantage of Catalog Zones to enable users to add new Web Parts to a page at runtime. You learned how to use Editor Zones to enable users to edit Web Part properties. Finally, you learned how to use Connections Zones to enable users to create dynamic connections between Web Parts.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset