I walked through my history list of posts today, and I can’t find any post about how to create a WebPart, so I decided to write about that even if most of you probably already know how to create a WebPart.
Introduction
There are two types of WebParts, Custom WebParts and Generic WebParts. A custom WebPart is a custom control that inherits the System.Web.UI.WebControls.WebParts.WebPart class. A custom control that doesn’t inherit the WebPart class and will be added to a WebPartZone (WebPartZone is a zone on the page where WebParts can located. A WebPart can’t live outside a WebPartZone), the custom control will be wrapped to a Generic WebPart.
Create a GenericWebPart
To create a Generic WebPart programmatically, you have to use the WebPartManager’s (WebPartManager, is a control on the page, that is the “manager” over the WebParts. It must be located on the page where you want to use WebParts) CreateWebPart method:
GenericWebpart webPart = MyWebPartManager.CreateWebPart(LoadControl(“myUserControl.ascx”));
…
MyWebPartManager.AddWebPart(webPart, WebPartZone1, 0);
You can also declarative add a control into a WebPartZone:
<asp:WebPartZone ID="WebPartZone1" runat="server">
<ZoneTemplate>
<uc:MyUserControl ruant="server" .... />
</ZoneTemplate>
</asp:WebPartZone>
The declarative added custom control will also be wrapped to a Generic WebParts. You can add the following attributes to your custom control to specify some WebPart specific options:
CatalogIconImageUrl
Description
Subtitle
Title
TitleIconImageUrl
TitleUrl
If the above attributes are added to the custom control, they will be added to the control’s Attributes collection and will be collected from the Generic WebPart’s properties with the same name:
<asp:WebPartZone ID="WebPartZone1" runat="server">
<ZoneTemplate>
<uc:MyUserControl ruant="server" Title="My Title" Description="Description" .... />
</ZoneTemplate>
</asp:WebPartZone>
You can also implement the IWebPart interface, which also has the above properties. If the IWebPart interface is implemented, the Generic WebPart will get the value from the properties from the custom control instead of the control’s Attribute collection.
If you want to get the custom control wrapped to a Generic WebPart, you can use the GenericWebPart’s ChildControl method:
GenericWebPart myWebPart = MyWebPartManager1.WebParts[0] as GenericWebPart;
If (myWebPart != null)
Control control = myWebPart.ChildControl;
Create a Custom WebPart
To create a Custom WebPart, you have to inherit the System.Web.UI.WebControls.WebParts.WebPart class:
using System.Web.UI.WebControls.WebParts;
public class MyWebPart : WebPart
{
}
A Custom WebPart is similar to a Custom Control, where you can either render the content of the control by over riding the Render method:
protected override void Render(HtmlTextWriter writer)
{
writer.WriteBeginTag("h1");
writer.Write("My WebPart");
writer.WriteEndTag("h1");
}
or add controls, by overriding the CreateChildControl method:
protected override void CreateChildControls()
{
this.Controls.Clear();
this.Controls.Add(new LiteralControl(”<h1>My WebPart</h1>”));
}
The WebPart class has several members, for example Title, for setting or by getting the title of the WebPart, Width and Height to set the size of the WebPart etc. I will not write about those members in this post, you can find all of them in the documentation.
The WebPart’s Personalization feature
The WebPart framework can personalize the WebParts on a page. The WebPart’s Personalization feature is a provider based solution, so you can create your own personalization provider by inherit the PersonalizationProvider class. Every property added to your WebPart class marked with the PersonalizableAttribute will be automatically saved or collected by the WebPart’s Personalization feature. There are two personalization scopes that could be specified for the PersonalizableAttribute, shared and user scope. With share scope, you will share all the settings made for the WebParts on a page with everyone. With user scope, every user can has its own setting for the WebParts. The following code has two properties, one for user scope, and the other for shared scope:
[Personalizable(PersonalizationScope.User), WebBrowsable]
public string Message
{
get { return this._privateMessage; }
set { this._privateMessage = value; }
}
[Personalizable(PersonalizationScope.Shared), WebBrowsable]
public string PublicMessage
{
get { return this._publicMessage; }
set { this._publicMessage = value; }
}
The above example has a WebBrowsableAttribute. With the WebBrowsableAttribute, you can specify if the property should be displayed in a PropertyGridEditorPart. To change the settings for WebParts on a page, for example in which zone a WebParts should exist and the size of the WebPart etc, you use EditorParts. An EditorPart must exist inside of an EditorZone. The PropertyGridEditorPart will be used to display the properties you have added to your WebPart class and marked with the WebBrowsableAttribute. By default the PropertyGridEditorPart will display the properties with its own names. By changing the names to be displayed for your properties in the PropertyGridEditorPart, you can use the WebDescription and WebDisplayName attribute:
[Personalizable(PersonalizationScope.User),
WebDescription("Private message description"),
WebDisplayName("Private message"),
WebBrowsable]
public string Message
{
get { return this._privateMessage; }
set { this._privateMessage = value; }
}
[Personalizable(PersonalizationScope.Shared),
WebDescription("Public message description"),
WebDisplayName("Public message"),
WebBrowsable]
public string PublicMessage
{
get { return this._publicMessage; }
set { this._publicMessage = value; }
}
The WebDescriptionAtrtibute is used to describe the property, and the WebDisplayName is the name displayed in the PropertyGridEditorPart for the property. Now when you have the basic understanding of how to create a WebPart, let’s take a look at some code.
The following code is an example of a WebPart:
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
public class MyWebPart : WebPart
{
private string _privateMessage = "Private message";
private string _publicMessage = "Public message";
public MyWebPart()
{
}
protected override void CreateChildControls()
{
this.Controls.Clear();
this.Controls.Add(new LiteralControl("Private Message: " + this._privateMessage + "<br>"));
this.Controls.Add(new LiteralControl("Public Message: " + this._publicMessage + "<br>"));
}
[Personalizable(PersonalizationScope.User),
WebDescription("Private message description"),
WebDisplayName("Private message"),
WebBrowsable]
public string Message
{
get { return this._privateMessage; }
set { this._privateMessage = value; }
}
[Personalizable(PersonalizationScope.Shared),
WebDescription("Public message description"),
WebDisplayName("Public message"),
WebBrowsable]
public string PublicMessage
{
get { return this._publicMessage; }
set { this._publicMessage = value; }
}
}
The following code will add a WebPart programmatically to a WebPartZone:
protected void Page_Load(object sender, EventArgs e)
{
if (WebPartZone1.WebParts.Count == 0)
{
MyWebPart webPart = new MyWebPart();
webPart.ID = "MyWebPart";
webPart.Title = "MyWebPart";
WebPartManager1.AddWebPart(webPart, WebPartZone1, 0);
}
}
The code above will only add the WebPart if there is no WebParts added to the WebPartZone1 zone. When the personalization is enabled and a WebPart is added. The WebPart will automatically displayed next time the page is requested, you don’t need to add it again. By using the WebPartMananger’s AddWebPart method, you can add a WebPart to a WebPartZone. The following code is a ASP.Net page with a WebpartManager, WebPartZone, EditorPart with a PropertyGridEditorPart control and two button controls, one for make it possible to edit WebParts, and the other button will toggle the scope into Shared scope.
<%@ Page Language="C#" %>
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
if (WebPartZone1.WebParts.Count == 0)
{
MyWebPart webPart = new MyWebPart();
webPart.ID = "MyWebPart";
webPart.Title = "MyWebPart";
WebPartManager1.AddWebPart(webPart, WebPartZone1, 0);
}
}
protected void Button1_Click(object sender, EventArgs e)
{
WebPartManager1.DisplayMode = WebPartManager.EditDisplayMode;
}
protected void Button2_Click(object sender, EventArgs e)
{
WebPartManager1.Personalization.ToggleScope();
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:WebPartManager ID="WebPartManager1" runat="server">
</asp:WebPartManager>
<asp:Button ID="Button1" runat="server" Text="Edit mode" OnClick="Button1_Click" />
<asp:Button ID="Button2" runat="server" Text="Toggle to shared scope" OnClick="Button2_Click" /></div>
<asp:WebPartZone ID="WebPartZone1" runat="server">
</asp:WebPartZone>
<asp:EditorZone ID="EditorZone1" runat="server">
<ZoneTemplate>
<asp:PropertyGridEditorPart ID="PropertyGridEditorPart1" runat="server" />
</ZoneTemplate>
</asp:EditorZone>
</form>
</body>
</html>
To run this example, you have to add the MyWebPart class, into the Application_Code (before \Code) folder and create the Asp.Net page above. When you run the example, the MyWebPart will be added to the WebPartZone1. When you press the “Edit mode” button, you can make the PropertyGridEdtiorPart visible by selecting the Edit menu option for the WebPart you want to edit. When you are in edit mode, the PropertyGridEditorPart will only display the PublicMessage property, because the PrivateMessage Property is marked with the PersonalizationAttribute set to shared scope. To make the shared scope property available, you have to grant the users or roles that are allowed to toggle to the shared scope. You can do that by adding the following code to your web.config file:
<webParts>
<personalization>
<authorization>
<allow verbs="enterSharedScope" users="*" />
</authorization>
</personalization>
</webParts>
The <allow> element will allow all users to enter shared scope. If you press the “Toggle to shared scope” button, you will know see both properties of MyWebPart. The value you enter for the PublicMessage property will be shared among all users that visit the page. The value you enter forthe PrivateMesssage in user scope, will only be displayed for the current logged in user (every user will have its own value if they change the value of the PublicMessage property).
Summary
In this post you have learned how to create a Generic Webpart and a Custom Webpart. You have also learned about some of the attributes that could be added to the WebPart, such as the PersonlizableAttribute to specify if the properties value should be handled by the Webpart Personalization feature etc.
Other post on my blog about the WebPart framework
The following posts on my blog could give you some more information about how to use the Webpart framework. Some of the posts can be out of date because they were written before Beta 1 of VS 2005. But you will still get some basic understanding out from the posts.
Import and Export WebParts
Show and Hide WebParts based on roles
GenericWebPart
How to build a EditorPart
CatalogPart example
WebPart that grabs content from an URL
Restore the personalization