Web Part Basics


You create a new web part project in the same way that you create any other project. When you select File New Project from the Visual Studio menu, you are presented with a set of project types from which to choose. Regardless of whether you choose C# or VB.NET, the project type is named "Web Part Library." When you create this project, the template generates four key files for you: the assembly information file, the manifest file, the code file, and the web part description file.

The assembly information file, AssemblyInfo.cs or AssemblyInfo.vb , contains assembly information such as the version. This information will be important when you are giving the web part permission to run inside of SPS. The manifest file, Manifest.xml , contains information important to the distribution of the web part. The code file, WebPart.cs or WebPart.vb , contains all of the code necessary for the web part to function. The web part description file, WebPart.dwp , contains metadata about the web part that SPS needs to upload the part and make it available for use in page design.

The WebPart Class

Creating a web part in Visual Studio is possible because Microsoft has provided an extensive set of .NET classes that allow access to nearly every facet of SharePoint Services. These classes are all defined within the SharePoint namespace. Throughout the book, we will be examining various pieces of the SharePoint namespace, but for now we will look closely at a single class: Microsoft.SharePoint.WebPartPages.WebPart . All web parts you construct must inherit from Microsoft.SharePoint.WebPartPages.WebPart , and depending upon the exact functionality you are trying to implement, you will have to override various methods of this class.

The first thing to note about the WebPart class is that it inherits from the System.Web.UI.Control class. This is exactly the same class from which the class System.Web.UI.WebControls.WebControl inherits. This is significant because developers use the WebControl class to create custom ASP.NET controls that live in the Visual Studio toolbox. In fact, web parts behave almost exactly like custom ASP.NET controls. Both types of controls are accessible from a toolbox, both have properties that are set during the design of a user interface, and both have runtime behavior that is affected by the values of the properties. Figure 5-1 shows the class hierarchy that relates web parts and custom controls.

click to expand
Figure 5-1: The WebPart class hierarchy

When you create a new web part project in Visual Studio .NET, a new class is generated that inherits from the WebPart class. The project also decorates the class with three attributes that affect its behavior. The following code shows a template class declaration in C#.

 [DefaultProperty("Text"), ToolboxData("<{0}:WebPart1 runat=server></{0}:WebPart1>"), XmlRoot(Namespace="HelloCS")] public class WebPart1 : Microsoft.SharePoint.WebPartPages.WebPart { } 

The DefaultProperty and ToolboxData attributes are exactly the same attributes found in an ASP.NET custom control. These attributes exist to govern the behavior of the control in a full-scale design environment such as Visual Studio .NET. These attributes show clearly that web parts are a specialized version of exactly the same components that Visual Studio developers drag onto ASP.NET web pages. Compare the previous code with the following code, which is a class declaration for an ASP.NET custom control written in VB.NET.

 <DefaultProperty("Text"), _ ToolboxData("<{0}:WebCustomControl1 runat=server> _ </{0}:WebCustomControl1>")> _ Public Class WebCustomControl1     Inherits System.Web.UI.WebControls.WebControl End Class 

A close examination of the two code fragments will reveal that the web part code has one additional attribute not found in the ASP.NET custom control code ”the XmlRoot attribute. This attribute is specific to web parts and is used as the root element when an instance of the web part is serialized to XML. This serialization maintains the state of the control and is part of the web part framework found in SharePoint Services.

The relationship between web parts and ASP.NET custom controls just demonstrated is so strong that you can actually add web parts to the toolbox in Visual Studio .NET. Once in the toolbox, the web parts can be dragged onto a web page in an ASP.NET project. However, this is really not the recommended use for a web part because Visual Studio .NET does not support the same infrastructure as SharePoint Services. Therefore, although an ASP.NET application is similar to a SharePoint Services site, it is not capable of providing all of the features such as web part connections or in-browser page design.

The Web Part Life Cycle

Just like ASP.NET controls, web parts participate in a server-side request/response sequence that loads a page in the portal each time it is requested and unloads the page once it is sent to the client. Web parts, therefore, follow the same control life cycle that ASP.NET controls follow. This life cycle supports a state management system that makes the portal appear to the end user like they are interacting with a stateful system, when in fact each request for a page is a separate operation.

When a page from a SharePoint Services site that contains web parts is requested for the first time ”or when it is submitted to the server ”the web part life cycle begins. The first phase in this life cycle is initialization. The initialization phase is marked by a call to the OnInit method of the WebPart class. During initialization, values from the web part storage system are loaded into the web part. These values are created when the web part page is designed.

SharePoint Services supports either a single set of shared values that are applied to all portal users or a set for each individual user. Each property in a web part may be designated to support shared or personal values. Additionally, web parts may be modified in a shared or personal view by end users with appropriate permissions. All of these elements combine to determine the initial set of property values that will be loaded into the web part.

After the web part is initialized , the ViewState of the web part is populated . ViewState is a property inherited from System.Web.UI.Control . The ViewState is filled from the state information that was previously serialized into a hidden field in the web page. Once the ViewState property is populated, the control returns to the same state it was in when it was last processed on the server. The ViewState is populated through a call to the LoadViewState method.

Once the web part has returned to its previous state, the server can make changes to the properties of the web part based on values that were posted by the client browser. Any new values that were posted during the request ”such as text field values ”are applied to the corresponding property of the web part. At this point, the web part has reached the state intended by the end user.

After all of the new property values are applied to the web part, the page may begin using the information to process the end user request. This begins through a call to the OnLoad event of the WebPart class. The OnLoad event fires for every web part regardless of how many properties have changed. Web part developers use the OnLoad event as the basis for the functionality embodied in the web part. During this event, web parts may access a database or other system to retrieve information for display. The key thing to remember about this event is that it always fires after the posted data has been applied to the web part.

Once the OnLoad event completes, any events triggered by the client interaction with the web part are fired . This includes all user-generated events such as the Click event associated with a button. It is critical for the web part developer to understand that the user-generated events happen after the OnLoad event. This means that you must be careful not to rely on the results of user-generated events when you write code for the OnLoad event.

Once the web part has finished handling the user-generated events, it is ready to create the output of the control. The web part begins creating this output with a call to the OnPreRender event of the WebPart class. The OnPreRender event gives the web part developer the opportunity to change any of the web part properties before the control output is drawn. This is the perfect place to run a database query that relies on several user-supplied values because all of the values will be available at this point in the life cycle.

After the OnPreRender event is complete, the ViewState of the web part is serialized and saved to a hidden field in the web page. The ViewState is saved through a call to the SaveViewState event, which is inherited from the System.Web.UI.Control class.

Once the ViewState is saved, the web part output may be drawn. Drawing begins through a call to the RenderWebPart event. In this method, the web part must programmatically generate its HTML output. This output will be rendered in the appropriate zone on the page in the portal.

After the output is rendered, the control web part can be removed from the memory of the server. Web parts receive notification that they are about to be removed from memory through the Dispose event. This method allows the web part developer to release critical resources such as database connections before the web part is destroyed .

The web part life cycle ends when it is finally removed from memory. The last event to fire is the OnUnload event. This event notifies the web part that it is being removed from memory. Generally web part developers do not need access to this event because all cleanup should have been accomplished in the Dispose event.

Understanding the complete life cycle helps significantly when developing web parts. In particular, understanding when certain values are available to the web part will ensure that you create components with consistent behavior. Figure 5-2 summarizes the life cycle in a flowchart.

click to expand
Figure 5-2: The web part life cycle

Web Part Properties

Well-designed web parts function in a variety of different pages because they are configurable by an administrator or end user directly in the portal. This configuration is possible because each web part supports a series of properties that can be set in the portal and read by the web part at runtime. In code, these properties are created in the same manner as any property for any class with the exception that they have special decorations that determine their behavior within the design environment of SPS. The process of creating a property begins with a standard property construct. This involves declaring a member variable to hold the value and a get/set construct to set and retrieve the value. Listing 5-1 shows a typical property defined using C#.

Listing 5-1: Creating a Property in C#
start example
 private string m_text; public string Text {     get     {          return m_text;     }     set     {          m_text = value;     } } 
end example
 

Property Basics

Most properties are designed to be configured directly in the portal. Therefore, you must decorate the property with different attributes to define its behavior when a page is designed. These property values are subsequently serialized and saved when the page is processed so that the property values can be read later when an end user accesses the page. Each of the properties you define is decorated with the Browsable , Category , DefaultValue , WebPartStorage , FriendlyName , and Description attributes.

The Browsable attribute is a Boolean value that determines whether or not the property appears in the tool pane during design time. You may set this value to either True or False . Although most of your properties will be browsable, you may have sensitive properties that should not be accessible by general portal users. The advantage of using a nonbrowsable property is that the value is still serialized and saved even though it cannot be set in the portal. In these cases, the web part itself is setting the value in code.

The Category attribute is a String value that determines the category in the tool pane where the property should appear. Using this attribute, you may have the property appear in a standard category like Appearance or you may create your own custom category. Generally, you should try to observe a logical placement that corresponds to the way most of the standard web parts work.

The DefaultValue attribute specifies the value of the property when the web part is first placed on a page. The exact value of the attribute is dependent upon the data type of the property itself. When setting a default value in the attribute, recognize that this does not actually change the value of the property itself. In order to ensure that the actual default value is in sync with the DefaultValue attribute, be sure to set the value of the member variable in code.

The WebPartStorage attribute is an enumeration that determines whether the property values are saved for an individual or for all users of the page on which the web part sits. This attribute may be set to Storage.None , Storage.Personal , or Storage.Shared . When the attribute is set to Storage.None , the property is not serialized and saved to the web part storage system. When the attribute is set to Storage.Personal , the property value may be set for each user of a page. The web part infrastructure serializes and saves the values separately for each user. Finally, when the attribute is set to Storage.Shared , the web part infrastructure saves only a single value of the property that is applied to all users of the page on which the web part sits.

The FriendlyName and Description attributes are both String values that are used to display a name and description for the property in the tool pane. These are both straightforward attributes that are obvious in their use. The only thing to watch out for here is consistency. Use the same names and descriptions for the same properties across all web parts you create. This will make them much easier to understand and configure.

Once you understand the property definition scheme, you can create as many as you need to properly configure the web part. Although they are easy to change, I recommend that you spend some time designing your web part before implementing the property set. If you think through the intended use of the web part, you will save yourself a lot of wasted time writing and rewriting property structures. As a final example, Listing 5-2 shows a complete property structure in VB.NET.

Listing 5-2: Defining a Web Part Property
start example
 Dim m_DatabaseName As String <Browsable(true),Category("Miscellaneous"), _ DefaultValue(""),WebPartStorage(Storage.Personal),FriendlyName("Database"), _ Description("The database to access")> _ Property DatabaseName() As String     Get          Return m_DatabaseName     End Get     Set(ByVal Value As String)         m_DatabaseName = Value     End Set End Property 
end example
 

Rendering Web Parts

Because the WebPart class inherits from System.Web.UI.Control , the entire user interface for a web part must be created through code. There is no drag-and-drop user interface design in a web part. This approach is definitely a drawback and can slow your ability to create web parts. Be that as it may, it becomes less of an issue once you have created a few web parts and learned the techniques for generating the user interface.

Properly rendering a web part requires that you first create any ASP.NET controls that you will need in code. The required ASP.NET controls are then added to the controls collection of the web part by overriding the CreateChildControls method of the base class. Finally, you can draw the output by overriding the RenderWebPart method.

You may use any available ASP.NET control found in Visual Studio .NET or any ASP.NET control you have written to create the user interface for a web part. Remember, however, that these controls cannot be dragged onto a page. Instead, they must be declared in code.

When you declare ASP.NET controls in code, be sure to set a reference to the appropriate namespace. Nearly all of the ASP.NET controls that you could want belong to the System.Web.UI.WebControls namespace. Therefore, you should reference them in code using the following C# or VB.NET declaration.

 //C# using System.Web.UI.WebControls; 'VB.NET Imports System.Web.UI.WebControls 

Once the appropriate namespace is referenced, you may create instances of the controls. When you create these instances, be sure to create them with their associated events. This way, you will have access to all of the events for any control you use. The following code shows an example of declaring several ASP.NET controls in VB.NET using the WithEvents keyword.

 'Controls to appear in the web part Protected WithEvents txtSearch As TextBox Protected WithEvents btnSearch As Button Protected WithEvents lstData As ListBox Protected WithEvents lblMessage As Label 

Once the controls are declared, you can set their properties and add them to the Controls collection of the web part. You can do this by overriding the CreateChildControls method. In this method, set property values for each control and then add it to the Controls collection using the Controls.Add method. Listing 5-3 shows several controls being added to a web part.

Listing 5-3: Adding ASP.NET Controls to a Web Part
start example
 Protected Overrides Sub CreateChildControls()     'Purpose: Add the child controls to the web part     'Text Box for Search String     txtSearch = New TextBox     With txtSearch         .Width = Unit.Percentage(100)         .Font.Name = "arial"         .Font.Size = New FontUnit(FontSize.AsUnit).Point(8)     End With     Controls.Add(txtSearch)     'Button to initiate searching     btnSearch = New Button     With btnSearch         .Text = "Search!"         .Font.Name = "arial"         .Font.Size = New FontUnit(FontSize.AsUnit).Point(8)     End With     Controls.Add(btnSearch)     'List to display results     lstData = New ListBox     With lstData         .AutoPostBack = True         .Width = Unit.Percentage(100)         .Font.Name = "arial"         .Font.Size = New FontUnit(FontSize.AsUnit).Point(8)         .Rows = 5     End With     Controls.Add(lstData)     'Label for error messages     lblMessage = New Label     With lblMessage         .Width = Unit.Percentage(100)         .Font.Name = "arial"         .Font.Size = New FontUnit(FontSize.AsUnit).Point(10)         .Text = ""     End With     Controls.Add(lblMessage) End Sub 
end example
 

When coding a web part in C#, you follow the same general ideas; however, you must manually connect events to the ASP.NET controls in the web part. Once the event is connected, you must also define an event handler in code. Listing 5-4 shows a simple example of declaring an ASP.NET TextBox and Button .

Listing 5-4: Adding ASP.NET Controls in C#
start example
 protected TextBox txtDisplay; protected Button btnGo; protected override void CreateChildControls() {     this.btnGo.Click += new System.EventHandler(this.btnGo_Click);     this.Controls.Add(btnGo);     txtDisplay.Width=Unit.Percentage(100);     this.Controls.Add(txtDisplay); } private void btnGo_Click(object sender, System.EventArgs e) {     txtDisplay.Text=Text; } 
end example
 

Once the controls are all configured and added to the web part, you are ready to draw the output. When rendering the user interface of the web part, you use the HtmlTextWriter class provided by the RenderWebPart method. This class allows you to create any manner of HTML output for the web part. The following code fragments show how to override the RenderWebPart method in both C# and VB.NET.

 //C# protected override void RenderWebPart(HtmlTextWriter output)     {     } 'VB.NET Protected Overrides Sub RenderWebPart _ (ByVal output As System.Web.UI.HtmlTextWriter) End Sub 

As a general rule, you should render your user interface within an HTML <TABLE> . The reason for this is that you can never be sure what the web part page layout will look like. As you saw in the last chapter, layouts and web part zones can take almost any form. Therefore, you should use the relative layout offered by the <TABLE> tag to respect the width defined by the zone where the web part appears. Listing 5-5 shows how to render a table containing ASP.NET controls. You should take particular note of the WIDTH definition within the table.

Listing 5-5: Rendering ASP.NET Controls in an HTML Table
start example
 With output     .Write("<TABLE BORDER=0 WIDTH=100%>")     .Write("<TR>")     .Write("<TD Width=70%>")     txtCompany.RenderControl(output)     .Write("</TD>")     .Write("<TD>")     btnSearch.RenderControl(output)     .Write("</TD>")     .Write("</TR>")     .Write("<TR>")     .Write("<TD COLSPAN=2>")     grdNames.RenderControl(output)     .Write("</TD>")     .Write("</TR>")     .Write("<TR>")     .Write("<TD COLSPAN=2>")     lblMessage.RenderControl(output)     .Write("</TD>")     .Write("</TR>")     .Write("</TABLE>") End With 
end example
 



Microsoft SharePoint[c] Building Office 2003 Solutions
Microsoft SharePoint[c] Building Office 2003 Solutions
ISBN: 1590593383
EAN: N/A
Year: 2006
Pages: 92

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net