Technically, there are two types of Web Parts. You can create a Web Part by adding any ASP.NET controlincluding any custom control or User controlto a Web Part Zone. Alternatively, you can create a Web Part by building a custom control that derives from the base WebPart class. The Web Part Framework handles these two types of Web Parts differently. When you add a standard ASP.NET control to a Web Part Zone, the Web Part Framework wraps the control in a GenericWebPart control. Wrapping a standard control in a GenericWebPart adds all the standard Web Part properties to the control. For example, if you add an Image control to a Web Part Zone, the Web Part Framework automatically creates a new GenericWebPart control that includes the Image control as its only child control. If, on the other hand, you create a Web Part by building a custom control that derives from the base WebPart class, the Web Part Framework doesn't need to do anything special with the control. The control is already a Web Part. Because the GenericWebPart class itself derives from the base WebPart class, you can do anything with a generic Web Part that you can do with a "True" Web Part with one important limitation. Because a control gets wrapped in a GenericWebPart at runtime, there are a number of Web Part properties that you cannot set declaratively when working with a generic Web Part. In this section, you learn how to create simple Web Parts. You also learn how to take advantage of both the core and extended properties supported by Web Part controls. The Hello World Web Part All authors of programming books are contractually obligated to include at least one Hello World sample in every book that they write. In this section, two Hello World Web Parts illustrate how to create a Web Part with a User control and a custom control derived from the base WebPart class. In other words, both a Generic Web Part and a True Web Part are created. The Generic Hello World Web Part is contained in Listing 28.1. Listing 28.1. HelloWorldPart.ascx <%@ Control Language="VB" ClassName="HelloWorldPart" %> Hello World! | Notice how simple the Generic Hello World Web Part is. The control simply renders a single line of text. Creating a True Web Part that does the same thing isn't that much more difficult. The Web Part in Listing 28.2 inherits from the base WebPart class, making it a True Web Part. Listing 28.2. App_Code\HelloWorldPart.vb Imports System Imports System.Web.UI Imports System.Web.UI.WebControls.WebParts Namespace myControls ''' <summary> ''' True Web Part ''' </summary> Public Class HelloWorldPart Inherits WebPart Protected Overrides Sub RenderContents(ByVal writer As HtmlTextWriter) writer.Write("Hello World!") End Sub End Class End Namespace | The class in Listing 28.2 inherits from the base WebPart class and overrides the RenderContents() method to display the single line of text. Note You must add the file in Listing 28.2 to the App_Code folder for the control to be automatically compiled. The page in Listing 28.3 displays both the Generic and True Web Parts. Listing 28.3. ShowHelloWorldPart.aspx <%@ Page Language="VB" %> <%@ Register TagPrefix="custom" Namespace="myControls" %> <%@ Register TagPrefix="user" TagName="HelloWorldPart" src="/books/3/444/1/html/2/~/HelloWorldPart.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 runat="server"> <style type="text/css"> .column { float:left; width:45%; height:200px; margin-right:10px; border:solid 1px black; background-color: white; } html { background-color:#eeeeee; } </style> <title>Show Hello World Part</title> </head> <body> <form runat="server"> <asp:WebPartManager Runat="server" /> <asp:WebPartZone Css Runat="server"> <ZoneTemplate> <user:HelloWorldPart Runat="server" /> </ZoneTemplate> </asp:WebPartZone> <asp:WebPartZone Css Runat="server"> <ZoneTemplate> <custom:HelloWorldPart Runat="server" /> </ZoneTemplate> </asp:WebPartZone> </form> </body> </html> | After you open the page in Listing 28.3, you'll see two Web Part Zones. The Generic Hello World Web Part is contained in the first zone and the True Web Part is contained in the second zone (see Figure 28.1). Figure 28.1. The Hello World Web Parts. Notice that both Web Parts are registered at the top of the page. As an alternative to registering Web Parts in each page, you can register the Web Parts once in an application's web configuration file, as is shown in Listing 28.4. Listing 28.4. Web.Config <?xml version="1.0"?> <configuration> <system.web> <pages> <controls> <add tagPrefix="custom" namespace="myControls" /> <add tagPrefix="user" tagName="HelloWorldPart" src="/books/3/444/1/html/2/~/WebParts/HelloWorldPart.ascx"/> </controls> </pages> </system.web> </configuration> | When you register a User control in the web configuration file, you must place the User control in a different folder than any page that uses it (otherwise, you'll get an exception). Typically, you should locate all your user controls in a subfolder in your application. In the web configuration file in Listing 28.4, the HelloWorldPart.ascx file has been moved to a folder named WebParts. Standard Web Part Properties As mentioned earlier, both Generic and True Web Parts support a core set of properties: AuthorizationFilter Enables you to specify a string that the Web Part Manager can check before adding a Web Part to a page. CatalogIconImageUrl Enables you to specify the icon displayed for the Web Part when the Web Part is listed in a Catalog Part. Description Enables you to specify the description displayed for the Web Part as a tooltip when you hover your mouse over the Web Part. ExportMode Enables you to export a Web Part control's settings to an XML file. Possible values are All, None, and NonSensitiveData. Height Enables you to specify the height of a Web Part control. Subtitle Enables you to add an additional string to the end of the title displayed in a Web Part. Title Enables you to specify the title of the Web Part displayed, for example, in the title bar. TitleIconImageUrl The title icon image is displayed next to the title in the title bar. TitleUrl Enables you to convert the title into a hyperlink that links to a page with more information about the Web Part. Width Enables you to specify the width of the Web Part. You can set any of these properties declaratively on any control that you add to a Web Part Zone. For example, you can set the Title and Description properties like this: <user:HelloWorldPart Title="Hello World" Description="Displays Hello World" Runat="server" /> Visual Web Developer Note When working in Source view in Visual Web Developer, you get a green squiggle warning when setting Web Part properties such as the Title or Description property for a User control. Technically, you are setting expando properties because the UserControl class doesn't know anything about the specialized Web Part properties. You can safely ignore the warning messages. Alternatively, you can supply any of these properties with default values in the Web Part control itself. You set these properties in different ways depending on whether you are working with a Generic Web Part control or a True Web Part control. When setting default Web Part property values for a Generic Web Part control, you need to implement the IWebPart interface. For example, Listing 28.5 contains the code for a Random Quote Web Part. Listing 28.5. RandomQuotePart.ascx <%@ Control Language="VB" ClassName="RandomQuotePart" %> <%@ Implements Interface="System.Web.UI.WebControls.WebParts.IWebPart" %> <%@ Import Namespace="System.Collections.Generic" %> <script runat="server"> Private _title As String = "Random Quote" Private _titleUrl As String = "~/Help.aspx" Private _description As String = "Displays a random quote" Private _subTitle As String = "User Control Version" Private _catalogIconImageUrl As String = "~/Images/BigRandomQuote.gif" Private _titleIconImageUrl As String = "~/Images/SmallRandomQuote.gif" Public Property Title() As String Implements IWebPart.Title Get Return _title End Get Set(ByVal Value As String) _title = Value End Set End Property Public Property TitleUrl() As String Implements IWebPart.TitleUrl Get Return _titleUrl End Get Set(ByVal Value As String) _titleUrl = Value End Set End Property Public Property Description() As String Implements IWebPart.Description Get Return _description End Get Set(ByVal Value As String) _description = Value End Set End Property Public ReadOnly Property Subtitle() As String Implements IWebPart.Subtitle Get Return _subTitle End Get End Property Public Property CatalogIconImageUrl() As String Implements IWebPart.CatalogIconImageUrl Get Return _catalogIconImageUrl End Get Set(ByVal Value As String) _catalogIconImageUrl = Value End Set End Property Public Property TitleIconImageUrl() As String Implements IWebPart.TitleIconImageUrl Get Return _titleIconImageUrl End Get Set(ByVal Value As String) _titleIconImageUrl = Value End Set End Property Private Sub Page_PreRender() Dim quotes As New List(Of String) quotes.Add("All paid jobs absorb and degrade the mind -- Aristotle") quotes.Add("No evil can happen to a good man, either in life or after death -- Plato") quotes.Add("The only good is knowledge and the only evil is ignorance -- Plato") Dim rnd As New Random() lblQuote.Text = quotes(rnd.Next(quotes.Count)) End Sub </script> <asp:Label runat="server" /> | Notice that the User control in Listing 28.5 implements the IWebPart interface. It includes an <%@ Implements %> directive at the top of the file. Default values are provided for each of the standard Web Part properties. When working with a True Web Part control, you do not need to implement the IWebPart interface. Because a True Web Part control derives from the base WebPart class, and the WebPart class contains all the properties of the IWebPart interface, you simply need to override the Web Part properties that you want to modify. The Web Part in Listing 28.6 also displays a random quotation. However, this control is a True Web Part control. Listing 28.6. App_Code\RandomQuotePart.vb [View full width] Imports System Imports System.Collections.Generic Imports System.Web.UI Imports System.Web.UI.WebControls.WebParts Namespace myControls ''' <summary> ''' Displays a random quotation ''' </summary> Public Class RandomQuotePart Inherits WebPart Private _title As String = "Random Quote" Private _titleUrl As String = "~/Help.aspx" Private _description As String = "Displays a random quote" Private _subTitle As String = "True Web Part Version" Private _catalogIconImageUrl As String = "~/Images/BigRandomQuote.gif" Private _titleIconImageUrl As String = "~/Images/SmallRandomQuote.gif" Public Overrides Property Title() As String Get Return _title End Get Set(ByVal Value As String) _title = value End Set End Property Public Overrides Property TitleUrl() As String Get Return _titleUrl End Get Set(ByVal Value As String) _titleUrl = value End Set End Property Public Overrides Property Description() As String Get Return _description End Get Set(ByVal Value As String) _description = value End Set End Property Public Overrides ReadOnly Property Subtitle() As String Get Return _subTitle End Get End Property Public Overrides Property CatalogIconImageUrl() As String Get Return _catalogIconImageUrl End Get Set(ByVal Value As String) _catalogIconImageUrl = value End Set End Property Public Overrides Property TitleIconImageUrl() As String Get Return _titleIconImageUrl End Get Set(ByVal Value As String) _titleIconImageUrl = value End Set End Property Protected Overrides Sub RenderContents(ByVal writer As HtmlTextWriter) Dim quotes As New List(Of String)() quotes.Add("All paid jobs absorb and degrade the mind -- Aristotle") quotes.Add("No evil can happen to a good man, either in life or after death -- Plato") quotes.Add("The only good is knowledge and the only evil is ignorance -- Plato") Dim rnd As New Random() writer.Write(quotes(rnd.Next(quotes.Count))) End Sub End Class End Namespace | Notice that the class in Listing 28.6 overrides the properties of the base WebPart class. For example, the RandomQuotePart class overrides the Title property of the base WebPart class to display a default title for the Web Part (see Figure 28.2). Figure 28.2. Displaying random quotations. CD Note You can view the RandomQuotePart with the ShowRandomQuotePart.aspx page included on the CD which accompanies this book. Creating a User Control Web Part Base Class Implementing the IWebPart interface in a User Control every time you want to supply a default value for a Web Part property quickly gets tedious. Because the IWebPart interface is an interface, you are obligated to implement all the properties included in the interface even if you need to supply a value for only one of the properties. To make your life easier, you can create a custom base class for every Web Part that you create with a User control. The UserControlWebPartBase class in Listing 28.7 creates default values for all the core Web Part properties. Listing 28.7. App_Code\UserControlWebPartBase.vb Imports System Imports System.Web.UI Imports System.Web.UI.WebControls.WebParts ''' <summary> ''' Base Class for User Control Web Parts ''' </summary> Public Class UserControlWebPartBase Inherits UserControl Implements IWebPart Private _title As String = "Untitled" Private _titleUrl As String = String.Empty Private _description As String = String.Empty Private _subTitle As String = String.Empty Private _catalogIconImageUrl As String = String.Empty Private _titleIconImageUrl As String = String.Empty Public Property Title() As String Implements IWebPart.Title Get Return _title End Get Set(ByVal Value As String) _title = Value End Set End Property Public Property TitleUrl() As String Implements IWebPart.TitleUrl Get Return _titleUrl End Get Set(ByVal Value As String) _titleUrl = Value End Set End Property Public Property Description() As String Implements IWebPart.Description Get Return _description End Get Set(ByVal Value As String) _description = Value End Set End Property Public ReadOnly Property Subtitle() As String Implements IWebPart.Subtitle Get Return _subTitle End Get End Property Public Property CatalogIconImageUrl() As String Implements IWebPart.CatalogIconImageUrl Get Return _catalogIconImageUrl End Get Set(ByVal Value As String) _catalogIconImageUrl = Value End Set End Property Public Property TitleIconImageUrl() As String Implements IWebPart.TitleIconImageUrl Get Return _titleIconImageUrl End Get Set(ByVal Value As String) _titleIconImageUrl = Value End Set End Property End Class | After you create the class in Listing 28.7, you can derive all your User Control Web Parts from this class. For example, the MinimalPart Web Part in Listing 28.8 inherits from the UserControlWebPartBase class. Listing 28.8. MinimalPart.ascx <%@ Control Language="VB" ClassName="MinimalPart" Inherits="UserControlWebPartBase" %> <script runat="server"> Sub Page_Load() Me.Title = "Minimal Part" Me.Description = "Displays hardly anything at all" End Sub </script> Minimal | The <%@ Control %> directive includes an Inherits attribute that causes the User Control to inherit from the base UserControlWebPartBase class. Notice that you are not obligated to implement all the properties of the IWebPart interface in the MinimalPart. Only the Title and Description properties are set. CD Note You can view the MinimalPart with the ShowMinimalPart.aspx page included on the CD that accompanies this book. Using Extended Web Part Properties True Web Parts are slightly more powerful than Generic Web Parts. Not all Web Part properties are exposed through the IWebPart interface. When deriving a Web Part from the base WebPart class, you can take advantage of any of the following properties: AllowClose Enables you to prevent users from closing a Web Part. AllowConnect Enables you to prevent users from connecting a Web Part. AllowEdit Enables you to prevent users from editing a Web Part. AllowHide Enables you to prevent users from hiding a Web Part. AllowMinimize Enables you to prevent users from minimizing (collapsing) a Web Part. AllowZoneChange Enables you to prevent users from moving a Web Part. AuthorizationFilter Enables you to specify a string that the Web Part Manager can check before adding a Web Part to a page. CatalogIconImageUrl Enables you to specify the icon displayed for the Web Part when the Web Part is listed in a Catalog Part. ChromeState Enables you to get or set whether a Web Part is currently minimized or maximized. Possible values are Minimized and Normal. ChromeType Enables you to get or set the appearance of a Web Part's chrome. Possible values are BorderOnly, Default, None, TitleAndBorder, and TitleOnly. ConnectErrorMessage Enables you to get the error message displayed when errors happen while Web Parts are connected. CreateEditorParts Enables you to associate particular Editor Parts with a Web Part. Description Enables you to specify the description displayed for the Web Part as a tooltip when you hover your mouse over the Web Part. ExportMode Enables you to specify whether a Web Part's settings can be exported to an XML file. HasSharedData Enables you to determine whether a Web Part has Shared Personalization data. HasUserData Enables you to determine whether a Web Part has User Personalization data. Height Enables you to specify the height of a Web Part control. HelpMode Enables you to specify the type of user interface displayed for help. Possible values are Modal, Modeless, and Navigate. HelpUrl Enables you to get or set the URL for a help page associated with the Web Part. Hidden Enables you to get or set whether a Web Part is hidden. When a Web Part is hidden, the Web Part is rendered with the Cascading Style Sheet attribute display:none. ImportErrorMessage Enables you to get or set the message displayed when an error occurs during the import process. IsClosed Enables you to determine whether a Web Part is closed. IsShared Enables you to determine whether a Web Part is visible to all users of a Web Part page. IsStandalone Enables you to determine whether a Web Part is visible to only certain users of a Web Part page. IsStatic Enables you to determine whether a Web Part is declared in a Web Part Zone (as opposed to being added from a Catalog Zone). Subtitle Enables you to add an additional string to the end of the title displayed in a Web Part. Title Enables you to specify the title of the Web Part displayed, for example, in the title bar. TitleIconImageUrl The title icon image is displayed next to the title in the title bar. TitleUrl Enables you to convert the title into a hyperlink that links to a page with more information about the Web Part. WebBrowsableObject Enables you to retrieve the object that is edited by an Editor Part. WebPartManager Enables you to get the WebPartManager control responsible for tracking a Web Part. Width Enables you to specify the width of the Web Part. Verbs Enables you to retrieve the collection of menu items displayed by a Web Part. Zone Enables you to get the zone that contains a Web Part. ZoneIndex Enables you to get the position of a Web Part in a zone. You can override any of these properties when building a True Web Part control. For example, Listing 28.9 contains a Web Part named the IrritatingPart. The IrritatingPart control is hidden and cannot be closed or minimized. Listing 28.9. App_Code\IrritatingPart.vb Imports System Imports System.Web.UI Imports System.Web.UI.WebControls.WebParts Namespace myControls ''' <summary> ''' Hidden Part that cannot be closed ''' or minimized. ''' </summary> Public Class IrritatingPart Inherits WebPart Private _title As String = "Irritating Part" Private _description As String = "This Web Part is irritating" Private _hidden As Boolean = True Private _allowClose As Boolean = False Private _allowMinimize As Boolean = False Public Overrides Property Title() As String Get Return _title End Get Set(ByVal Value As String) _title = Value End Set End Property Public Overrides Property Description() As String Get Return _description End Get Set(ByVal Value As String) _description = Value End Set End Property Public Overrides Property Hidden() As Boolean Get Return _hidden End Get Set(ByVal Value As Boolean) _hidden = Value End Set End Property Public Overrides Property AllowClose() As Boolean Get Return _allowClose End Get Set(ByVal Value As Boolean) _allowClose = Value End Set End Property Public Overrides Property AllowMinimize() As Boolean Get Return _allowMinimize End Get Set(ByVal Value As Boolean) _allowMinimize = False End Set End Property Protected Overrides Sub RenderContents(ByVal writer As HtmlTextWriter) writer.Write("<h1>You can't get rid of me!</h1>") End Sub End Class End Namespace | If you add the Web Part in Listing 28.9 to a page, then you won't be able to see the Web Part in Browse Display mode because the Web Part overrides the Hidden property to hide itself. You can only see the IrritatingPart when a page is in Design or Catalog Display mode. You also cannot close or minimize the Web Part because both these properties are also overridden (see Figure 28.3). Figure 28.3. An Irritating Web Part. CD Note You can view the IrritatingPart with the ShowIrritatingPart.aspx page included on the CD that accompanies this book. Note Of course, the IrritatingPart Web Part is not a very realistic sample of when you would use the Hidden property. When a Web Part is hidden, the Web Part is rendered but not visible. The Cascading Style Sheet display:none property is set. Using the Hidden property is useful when you want to add a non-visual Web Part to a page such as a data source Web Part that exposes all the records from the Movies database table. The Hidden Web Part can be connected to Web Parts that aren't hidden. You cannot set any of the properties discussed in this section declaratively in the case of a Generic Web Part. Because the controls in a Web Part Zone do not get wrapped in the GenericWebPart class until runtime, a Generic Web Part is not a Web Part until a page is actually executed. However, you can set any of these properties programmatically in the case of either a Generic or True Web Part. The GenericWebPart class derives from the base WebPart class, so you can do anything with a Generic Web Part that you can do with a True Web Part. The only requirement is that you do it programmatically rather than declaratively. For example, the page in Listing 28.10 contains three links for minimizing the Web Parts contained in the page (see Figure 28.4). Figure 28.4. Minimizing Web Parts. Listing 28.10. MinimizeWebParts.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"> ''' <summary> ''' Minimize All Web Parts ''' </summary> Protected Sub lnkMinimizeAll_Click(ByVal sender As Object, ByVal e As EventArgs) Dim part As WebPart For Each part In WebPartManager1.WebParts part.ChromeState = PartChromeState.Minimized Next End Sub ''' <summary> ''' Minimize Zone 1 Web Parts ''' </summary> Protected Sub lnkMinimizeZone1_Click(ByVal sender As Object, ByVal e As EventArgs) Dim part As WebPart For Each part In WebPartZone1.WebParts part.ChromeState = PartChromeState.Minimized Next End Sub ''' <summary> ''' Minimize Zone 2 Web Parts ''' </summary> Protected Sub lnkMinimizeZone2_Click(ByVal sender As Object, ByVal e As EventArgs) Dim part As WebPart For Each part In WebPartZone2.WebParts part.ChromeState = PartChromeState.Minimized Next End Sub </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <style type="text/css"> .column { float:left; width:30%; height:200px; margin-right:10px; border:solid 1px black; background-color: white; } html { background-color:#eeeeee; } </style> <title>Minimize Web Parts</title> </head> <body> <form runat="server"> <asp:WebPartManager Runat="server" /> <asp:LinkButton Text="Minimize All" Runat="server" OnClick="lnkMinimizeAll_Click" /> <div > <asp:LinkButton Text="Minimize" OnClick="lnkMinimizeZone1_Click" Runat="server" /> <asp:WebPartZone Runat="server"> <ZoneTemplate> <asp:Label Title="First Part" Text="First Part" Runat="server" /> <asp:Label Title="Second Part" Text="Second Part" Runat="server" /> </ZoneTemplate> </asp:WebPartZone> </div> <div > <asp:LinkButton Text="Minimize" OnClick="lnkMinimizeZone2_Click" Runat="server" /> <asp:WebPartZone Runat="server"> <ZoneTemplate> <asp:Label Title="Third Part" Text="Third Part" Runat="server" /> <asp:Label Title="Fourth Part" Text="Fourth Part" Runat="server" /> </ZoneTemplate> </asp:WebPartZone> </div> </form> </body> </html> | When you click the Minimize All link, the collection of all the Web Parts in the page is retrieved from the WebPartManager control, and the ChromeState property for each Web Part is set to the value Minimized. If you click the Minimize link associated with a particular zone, then the Web Parts are retrieved from the Zone's WebParts property and the Web Parts in the selected zone are minimized. Notice that the ChromeState property can be set, even for the Generic Web Parts (Labels) in the page. Because the Generic Web Parts are being retrieved from the WebPartManager and WebPartZone WebParts collection, the controls in the Web Part Zones have already been wrapped in the GenericWebPart class that includes all the properties of a True Web Part. By taking advantage of the WebParts property exposed by both the WebPartManager and WebPartZone controls, you can retrieve information about the Web Parts contained in a page. For example, the User control in Listing 28.11the WebPartInfo controldisplays several properties of the Web Parts contained in the page. Listing 28.11. WebPartInfo.ascx <%@ Control Language="VB" ClassName="WebPartInfo" %> <script runat="server"> Sub Page_PreRender() Dim wpm As WebPartManager = WebPartManager.GetCurrentWebPartManager(Page) grdInfo.DataSource = wpm.WebParts grdInfo.DataBind() End Sub </script> <asp:GridView AutoGenerateColumns="false" Runat="server"> <Columns> <asp:BoundField HeaderText="Title" DataField="Title" /> <asp:BoundField HeaderText="IsShared" DataField="IsShared" /> <asp:BoundField HeaderText="IsStatic" DataField="IsStatic" /> <asp:BoundField HeaderText="IsClosed" DataField="IsClosed" /> <asp:BoundField HeaderText="HasUserData" DataField="HasUserData" /> <asp:BoundField HeaderText="HasSharedData" DataField="HasSharedData" /> </Columns> </asp:GridView> | You can add the User Control in Listing 28.11 to any page to view the properties of the Web Parts in the page (see Figure 28.5). Figure 28.5. Displaying Information about Web Parts. CD Note You can view the information displayed by the WebPartInfo control by opening the ShowWebPartInfo.aspx page located on the CD that accompanies this book. |