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 PartsWhen 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:
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 PartsLet'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). 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. Listing 27.22. App_Code\IZIPCode.vb
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. Listing 27.23. ZIPCodePart.ascx
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. Listing 27.24. WeatherPart.ascx
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. Listing 27.25. ConnectedSimpleParts.aspx
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 PartsThis 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). 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. Listing 27.26. IMovieCategory.vb
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. Listing 27.27. MovieCategoryPart.ascx
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. Listing 27.28. MovieListPart.ascx
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. Listing 27.29. ConnectedDataParts.aspx
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 PartsIn 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. Listing 27.30. ConnectedDynamicParts.aspx
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. 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 PartsFor 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 Partnamed the LocalNewsPartthat 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. Listing 27.31. LocalNewsPart.ascx
The LocalNewsPart Web Part uses the interface defined in Listing 27.32the INewsZIPCode interfaceto represent a ZIP code. Listing 27.32. App_Code\INewsZIPCode.vb
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. Listing 27.33. App_Code\ZIPCodeTransformer.vb
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. Listing 27.34. Web.Config
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. Listing 27.35. ConnectedTransformerParts.aspx
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. |