Writing Custom Editors for WebParts

The following WebPart may be simplistic, but it contains a "personalizable" public property called DisplayText that could transform it into an incredibly useful content editor:

public class SimpleWebPart : WebPart
{
   private string displayText = "Hello World!";

   [WebBrowsable(true), Personalizable(true)]
   public string DisplayText
   {
      get { return displayText; }
      set { displayText = value; }
   }

   protected override void Render(System.Web.UI.HtmlTextWriter writer)
   {
      writer.Write(displayText);
   }
}

The WebPart simply renders out the text specified in DisplayText, and putting it in either Microsoft Office SharePoint Server 2007 or an ASP.NET 2.0 WebPart framework that you wrote yourself enables you to modify the DisplayText value. In the case of an ASP.NET 2.0 WebPart framework, you can modify it with the PropertyGridEditorPart because DisplayText is decorated by the WebBrowsable(true) attribute.

This article describes how to write a custom editor for a WebPart. (If you haven't already, read "ASP.NET 2.0: WebPart Framework Basics" for the necessary background to follow the discussion.) Because a custom editor written for an ASP.NET 2.0 WebPart is directly usable in SharePoint 2007, this article applies to both technologies equally well.

Custom Editor Basics

You could not only use the example WebPart as a content editor but also extend it into a cheap content management solution, particularly if you could hook it up with a standard Web-based HTML editor and give the user a better UI to edit his HTML than a tiny textbox. A number of free UI's are available, but this article uses the telerik r.a.d. editor to write a custom EditorPart, which will hook up with the simple example WebPart.

Writing a custom editor basically is a two-step process:

  1. The WebPart needs to tell the framework which specific editors it wants to use. The framework then will add those editors into the EditorZone.
  2. You need to write the editors themselves. These simply inherit from the System.Web.UI.WebControls.WebParts.Editor class.

Look at these steps in turn.

Writing the EditorPart

As mentioned previously, the editor simply inherits from the EditorPart class. This class will require you to implement two methods:

  1. ApplyChanges: This method is responsible for taking the user's current edits, as displayed in the editor, and apply them to the WebPart itself. In this case, this would mean setting a value to the DisplayText property.
  2. SyncChanges: This method is responsible for retrieving the current state of the WebPart and updating the editor itself to display the current state of the WebPart.

In either scenario, you can access the WebPart being edited by using the WebPartToEdit property available on the EditorPart itself.

With this knowledge, you can begin writing the EditorPart. Call it "HtmlEditor". Your HtmlEditor will inherit from the EditorPart class and show the telerik r.a.d. editor in its UI. The following code achieves this very easily:

public class HtmlEditor : EditorPart
{
   private RadEditor htmlContentTxt;

   public HtmlEditor()
   {
      this.ID    = "HtmlEditor";
   }

   protected override void CreateChildControls()
   {
      htmlContentTxt               = new RadEditor();
      htmlContentTxt.ToolsFile     = "~/ToolsFile.xml";
      htmlContentTxt.BackColor     = System.Drawing.Color.White;
      htmlContentTxt.EnableDocking = false;
      htmlContentTxt.ToolbarMode   = EditorToolbarMode.ShowOnFocus;
      htmlContentTxt.ShowSubmitCancelButtons = false;
      htmlContentTxt.Modules.Clear();
      htmlContentTxt.Width  = new Unit("475px");
      htmlContentTxt.Height = new Unit("150px");
      Controls.Add(htmlContentTxt);
   }

   public override bool ApplyChanges()
   {
      // not implemented yet
   }

   public override void SyncChanges()
   {
      // not implemented yet
   }
}

Next, you need to implement ApplyChanges so it "applies the user's changes to the WebPart":

public override bool ApplyChanges()
{
   EnsureChildControls();
   SimpleWebPart part = WebPartToEdit as SimpleWebPart;
   if (part != null)
   {
      part.DisplayText = htmlContentTxt.Html;
   }
   else
   {
      return false;
   }
   return true;
}

Finally, you have to implement the SyncChanges method, so the EditorPart can apply the current state of the data in the WebPart to itself:

public override void SyncChanges()
{
   EnsureChildControls();
   SimpleWebPart part = WebPartToEdit as SimpleWebPart;
   if (part != null)
   {
      htmlContentTxt.Html = part.DisplayText;
   }
}

That's it. You have set up your EditorPart. The next step is to tweak the WebPart itself, so it uses your EditorPart.

Modifying the WebPart Itself

First, you no longer want the PropertyGridEditorPart to be able to modify your DisplayText property. So, get rid of the WebBrowsable(true) attribute, thus making the PropertyGridEditor blind to this property.

For a WebPart to be custom-editable, it needs to implement the IWebEditable interface. This interface requires you to implement a property called WebBrowsableObject, which gets a reference to the WebPart control or whatever else is being edited. In most scenarios, this will be the WebPart itself. Notably, a custom user control or server control that is not a WebPart could implement this interface and be custom editable in ASP.NET 2.0. This obviously won't work in SharePoint 2007.

The IWebEditable interface also requires you to implement a method called CreateEditorParts, which simply returns a collection of custom EditorPart controls associated with this particular WebPart, or a server control or user control that implements the IWebEditable interface. Note that I wrote collection of custom EditorPart controls. This means, you have multiple editors working against the various properties on a WebPart. In most scenarios, however, you probably want one editor per property. Having more than one will cause the framework to confuse the values and double set and reset them. This is something you should be careful of.

The implementation of the IWebEditable interface on the SimpleWebPart looks like this:

#region IWebEditable Members

EditorPartCollection IWebEditable.CreateEditorParts()
{
   List<EditorPart> editors = new List<EditorPart>();
   editors.Add(new HtmlEditor());
   return new EditorPartCollection(editors);
}

object IWebEditable.WebBrowsableObject
{
   get { return this; }
}

#endregion

That's it! Your custom editor and your WebPart are now ready to use.

Writing Custom Editors for WebParts

Using the Custom Editor

To use the custom editor, set up a Web site in Visual Studio 2005 and add a reference to the class library that holds your WebPart and its EditorPart. You will have to perform the additional setup steps for the telerik r.a.d. control as well. This includes copying the ToolsFile.xml, the RadControls directory, and the various references. (For more help, see www.telerik.com.) Of course, you are not limited to using only the telerik control; you can use anything that will run in ASP.NET 2.0.

In the default.aspx, add a WebPartManager, two WebPartZones, an EditorZone, and a CatalogZone. Inside the CatalogZone's ZoneTemplate, add a DeclarativeCatalogPart. Inside the DeclarativeCatalogPart's WebPartsTemplate, add an instance of your SimpleWebPart. The changes to the default.aspx should look as follows:

<asp:WebPartManager  ="WebPartManager1" runat="server" />
<asp:WebPartZone     ="WebPartZone1"    runat="server" />
<asp:WebPartZone ID  ="WebPartZone2"    runat="server" />

<asp:CatalogZone ID  ="CatalogZone1"    runat="server">
   <ZoneTemplate>
      <asp:DeclarativeCatalogPart ID="DeclarativeCatalogPart1"
                                  runat="server">
         <WebPartsTemplate>
            <cc1:SimpleWebPart ID="SimpleWebPart1" runat="server">
            </cc1:SimpleWebPart>
         </WebPartsTemplate>
      </asp:DeclarativeCatalogPart>
   </ZoneTemplate>
</asp:CatalogZone>

<asp:EditorZone ID="EditorZone1" runat="server">
   <ZoneTemplate>
      <asp:PropertyGridEditorPart ID="PropertyGridEditorPart1"
                                  runat="server"/>
   </ZoneTemplate>
</asp:EditorZone>

With this set up, add three link buttons at the bottom of the page. These link buttons will set the appropriate display mode for the WebPartManager. The following is the aspx code for the link buttons:

<asp:LinkButton ID="Edit" runat="server"
                OnClick="Edit_Click">Edit</asp:LinkButton> |
<asp:LinkButton ID="Catalog" runat="server"
                OnClick="Catalog_Click">Catalog</asp:LinkButton> |
<asp:LinkButton ID="Browse" runat="server"
                OnClick="Browse_Click">Browse</asp:LinkButton>

Here is the code-behind for these:

protected void Edit_Click(object sender, EventArgs e)
{
   WebPartManager1.DisplayMode = WebPartManager.EditDisplayMode;
   }

protected void Catalog_Click(object sender, EventArgs e)
{
   WebPartManager1.DisplayMode = WebPartManager.CatalogDisplayMode;
}

protected void Browse_Click(object sender, EventArgs e)
{
   WebPartManager1.DisplayMode = WebPartManager.BrowseDisplayMode;
}

That's it. Press "F5" and run the Web application.

To begin with, you should see a UI like this:

[Sahil1.jpg]

Click the "Catalog" button to view the only control you added in the catalog. Select its checkbox and add an instance to WebPartZone1, as shown below:

[Sahil2.jpg]

The control should now show its default value. Click the "Edit" link button at the bottom of the page. The catalog should now disappear, and the WebParts and WebPartZones should be visible. The SimpleWebPart instance that you just added to the WebPartZone1 should have a tiny down-facing arrow right next to it. Clicking on that arrow displays a menu. Click on that arrow, and select "Edit" from the drop down menu as shown below:

[Sahil3.jpg]

By doing so, you will be able to see the r.a.d. editor in the EditorZone as shown here:

[Sahil4.jpg]

Just to be fancy, go to this link and copy and paste a nice looking area of that page into the rich HTML editor. Click "OK" to make your changes permanent, and then click on the "Browse" link button to view the page in action. You should see something like this:

[Sahil5.jpg]

Thus, you now have much more flexibility and the ease of editing the HTML displayed in your SimpleWebPart.

Feel free to experiment a bit more with this framework, and add further EditorParts that come in-built with the .NET 2.0 Framework. One such EditorPart that you may wish to add is the AppearanceEditorPart. You then could give a custom title to the content block you just created, or simply get rid of its title. You also can add further personalization options in the framework, tie the Web application with a sitemap and a URL rewriter, and get a quick-and-dirty content management solution that lacks any kind of workflow but enables you to set up and create an easily maintainable Web site rather cheaply.

Write Custom Editors for Your Various WebParts

Custom editors, along with WebParts, provide you with a fantastic set of building blocks for producing final solutions. You probably will need to write custom editors for your various WebParts in many scenarios. A simple task such as entering a date or time can be very error prone if the user is typing into a textbox. The task would be much smoother for the user if you leveraged one of the many standard third-party controls that can display a calendar or time picker on a Web page.

SharePoint 2007 will understand your editor parts just as easily as it understands your ASP.NET 2.0 WebParts. As long as you follow the security and deployment steps that SharePoint 2007 requires, it will automatically discover your custom editors and be show them in its EditorZone.

About the Author

Sahil Malik (www.winsmarts.com) has worked for a number of top-notch clients in Microsoft technologies ranging from DOS to .NET. He is the author of Pro ADO.NET 2.0 and co-author of Pro ADO.NET with VB.NET 1.1. Sahil is currently also working on a multimedia series on ADO.NET 2.0 for Keystone Learning. For his community involvement, contributions, and speaking, he has also been awarded the Microsoft MVP award.



Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds