Tag Archive for 'webpart'

SharePoint “Smart” Editor Parts

Stealing the name from Jan Tielens’ SmartPart for SharePoint, I’ve put together a framework for building “Smart” Editor Parts — “Smart” Editor Parts being User Controls that serve as Editor Parts.  This blog post is an excerpt from the complete writeup of the framework.

Downloads

SharePoint Smart Editor Parts.docx (~159 KB)
A complete writeup of the SharePoint “Smart” Editor Part framework

Trentacular.SharePoint.SmartEditorPart.zip (~ 320 KB)
The Visual Studio solution of the SharePoint “Smart” Editor Part framework
(Requires Visual Studio 2010 and WSPBuilder Extensions 2010)

Introduction

About the SharePoint Web Part Platform

Windows SharePoint Services 3.0 (WSS) offers a robust platform for hosting Web Parts, providing a Web Part Manager implementation that builds a rich tool pane for configuring the Web Parts.  Out of the box, WSS provides tool panes for customizing the appearance and layout, and will even generate basic fields for custom Web Part properties that are marked with the appropriate attributes.   The following table describes how custom property types are displayed in the property pane:

Custom Property Type Generated Property Pane Field
bool Check Box
DateTime Text Box
enum Dropdown List
int Text Box
string Text Box

Building Custom Editor Parts

When a custom property requires a user interface element other than the ones listed above or needs custom validation, you can write a custom Editor Part that inherits from System.Web.UI.WebControls.WebParts.EditorPart and have your Web Part implement System.Web.UI.WebControls.WebParts.IWebEditable to create your custom Editor Part.

If you would like to build your custom Editor Part using a User Control, there are a few more steps you will have to take, because the abstract System.Web.UI.WebControls.WebParts.EditorPart base class does not inherit from the System.Web.UI.UserControl class.  The rest of this guide will walk you through the steps to create a framework for building Editor Parts with User Controls.

Inheriting from a Web Part Base Class

Web Parts inheriting from Microsoft.SharePoint.WebPartPages.WebPart can also take advantage of this framework with slight modifications to this guide.  You will be creating a base class that inherits from System.Web.UI.WebControls.WebParts.WebPart that will encapsulate the majority of the Editor Part framework and will be used by the example Site Members Web Part.  If you prefer to inherit from Microsoft.SharePoint.WebPartPages.WebPart, you may change the base class you will be creating to inherit from this class instead; however, Microsoft recommends that you inherit from System.Web.UI.WebControls.WebParts.WebPart whenever possible.

Overview of the User Control Editor Part Framework

Overview of Building an Editor Part

In order for a Web Part to have a custom Editor Part, the Web Part can implement the System.Web.UI.WebControls.WebParts.IWebEditable interface.  The abstract WebPart class that is typically used as the base class for custom Web Part implementations already implements the IWebEditable interface, which includes two exposed members.  The WebBrowsableObject property provides a way for EditorPart controls to get a reference to the associated Web Part.  The CreateEditorParts method is used to create an instance of each custom EditorPart control associated with the Web Part, and return them as a collection.  Custom Web Parts that inherit from the abstract WebPart class need only to override the CreateEditorParts method in order to add additional Editor Parts.

The EditorPart class exposes a property named WebPartToEdit of type WebPart that the Editor Part can use to read and set the configurable properties of the Web Part.  Additionally, two abstract methods SyncChanges and ApplyChanges are exposed that are called by the Web Part framework at the appropriate times when the Editor Part should read or set these properties on the associated Web Part.

Extending the Editor Part Framework to Support User Controls

In order to use a User Control as an Editor Part, a generic Editor Part called UserControlEditorPart<T> is needed that will wrap the appropriate User Control.  The UserControlEditorPart<T> will also need to pass the SyncChanges and ApplyChanges method calls along to the User Control.  This can be accomplished by defining an interface to be implemented by the User Control.  This interface will be called IWebPartEditor<T>.

The UserControlEditorPart<T> class is generic because it will inherit from another base class that is also generic called BaseEditorPart<T>.  This base class is extracted so that it can be inherited by both the UserControlEditorPart <T> and any other custom non-User Control Editor Parts.  Its sole purpose is to provide the convenience of casting the WebPartToEdit property of the EditorPart abstract class to the specific Web Part type associated to the EditorPart.

Enabling Attribute Decorations for Editor Part Associations

While it is relatively straight-forward to implement the IWebEditable interface’s CreateEditorParts method in a custom Web Part class, the framework additionally abstracts this step away, enabling you to associate Editor Parts to your Web Part using attributes.  This is accomplished by supplying two additional classes: WebEditableWebPart and EditorPartAttribute.

The WebEditableWebPart class is a new base class to be used by your custom Web Parts.  The class inherits from WebPart and overrides the CreateEditorParts method to add any Editor Parts to the Web Part that are specified by the EditorPartAttribute class.

The EditorPartAttribute class is to be applied as a class attribute to a Web Part requiring a custom Editor Part.  The attribute allows for an Editor Part to be specified by either its type or by a virtual path to a User Control that implements IWebPartEditor<T>.

User Control Editor Part Framework Class Diagram

Using the User Control Editor Part Framework

With the User Control Editor Part framework in place, there are now just three steps needed in order to create an Editor Part as a User Control:

  1. Ensure the Web Part inherits from WebEditableWebPart.  In the case where you are already using a custom base class for your Web Parts, you may simply change your custom base class to inherit from WebEditableWebPart.
  2. Create a User Control that implements IWebPartEditor<T>.
  3. Decorate your Web Part using the EditorPartAttribute class specifying the virtual path to the User Control.

SharePoint Enhanced List View Web Part

I just published an enhanced List View Web Part in the Trentacular SharePoint 2007 Features CodePlex project. The Web Part is a substitute for the out of the box List View Web Part with two additional capabilities:

  • Toggling of views in place (without leaving the web part page)
  • Ability to display lists located in different sites of the same SharePoint Farm

Development of this Web Part has proved to be a very difficult undertaking, and I would love for any assistance or ideas with how to go about accomplishing this differently.

Here is where I’ve currently landed in the Web Part’s development:

  • I am accessing the SPLimitedWebPartManager at the selected view’s url to load the SharePoint List View Web Part that was provisioned for the view when created
  • I then use reflection to invoke the private RenderView method of the Web Part

Yes, this sounds extremely hacky, and it is. Using the avaliable SharePoint ListView control didn’t play nice with many custom views (especially when the list used managed content types).  I’ve also tried the SPView.RenderAsHtml method, but this also presented problems.

Another possible option would be to use the ListViewByQuery WebControl, but this would require an intense amount of code to duplicate the sorting and filtering that is available through the ListView control. So if you think this Web Part would be useful and would like to contribute to furthering it along, please get in touch.

Here are some screenshots:

Trentacular List View Web Part

Trentacular List View Web Part Editor

Generic Feature Receiver for Features that Deploy WebParts

Greg Galipeau wrote a thorough post on cleaning up your Web Part Gallery that is the basis for this post. To summarize, Greg shares a Feature Receiver he uses as a generic Feature Receiver for all his WebPart Features that simply removes the WebPart having the same name as the Feature’s DisplayName when the Feature is deactivated.

There are a couple of issues with this though:

  1. It assumes that the WebPart has the same name as the Feature
  2. It limits the Feature to deploying just a single WebPart

An alternative approach would be to inspect the Feature’s element definitions and extract the exact WebPart names that were deployed, thus resolving the two issues noted above.

Below is the alternative Feature Receiver (it extends the BaseFeatureReceiver I mentioned in my previous post):

    public class WebPartFeatureReceiver : BaseFeatureReceiver<SPSite>
    {
        public override void FeatureDeactivating(SPSite site, SPFeatureReceiverProperties properties)
        {
            base.FeatureDeactivating(site, properties);
 
            var elements = properties.Definition.GetElementDefinitions(CultureInfo.CurrentCulture);
            var webparts = elements.Cast<SPElementDefinition>()
                .SelectMany(e => e.XmlDefinition.ChildNodes.Cast<XmlElement>()
                    .Where(n => n.Name.Equals("File"))
                    .Select(n => n.Attributes["Url"].Value)
                    )
                .ToList();
 
            var rootWeb = site.RootWeb;
            var wpGallery = rootWeb.Lists["Web Part Gallery"];
 
            var galleryItems = wpGallery.Items.Cast<SPListItem>()
                .Where(li => webparts.Contains(li.File.Name))
                .ToList();
 
            for (int i = galleryItems.Count - 1; i >= 0; i--)
            {
                var item = galleryItems[i];
                item.Delete();
            }
        }
    }