Patrick's SharePoint Blog

SharePoint's Booming world

Personal Edit Mode Panel

Posted by Patrick Boom on February 24, 2011

Sometimes you encounter stuff in SharePoint that makes you go, ‘huh’? While I was working on the publishing features of SharePoint 2010, a client requested to have custom area on their Intranet where end-users could place their own web parts. Quite easy to achieve by just creating a WebPartZone and have the AllowPersonalization property set to true. So far as so good, but end-users now had to use the Welcome menu (the menu on the top right with your name) to enter the Personal Edit mode. But why not through a button, close to the zone itself that you can also style the way you want?

In short, you only need to call the javascript that is also called if you use the Welcome menu. This javascript is called ChangeLayoutMode(bool personalEdit). If you pass true, the interface is set into personal edit mode, which allows for editing of the WebPart zone with AllowPersonalization set to true. Passing false will set the interface into full edit mode, provided you have permissions of course.

Great, but we also want the button or link to change once in this mode to close this interface and switch to normal view again. Guess what? No such method or button. You close it by navigating away from the page and going back or reload it without QueryString parameters.

Ok, there should be an easier way to do this right? Asking end-users to just navigate away seems odd, so we need to provide a button that does just that, but looks like closing the edit mode. SharePOint comes with the EditModePanel out of the box and although its behavior has been changed slightly since SharePoint 2007, I want something similar for the personal edit mode. That is, just a control that we can include in the master page that shows its contents based on the edit mode active.

Let’s start coding 😉

Setting up the solution

Open Visual Studio 2010 and create a new empty SharePoint project. We will not add any features in this solution. Instead, we just add three classes to the root of the project. I called them PersonalModePanel, PersonalModeDisplay and PersonalModePanelDesigner. The first class will be our control. The second class will contain an enumeration for the different display modes. The last class will be the designer class to enable design time support.


PersonalModeDisplay.cs

Let’s start with the easiest one, although none of the classes are difficult. The PersonalModeDisplay is an enumeration that defines the display modes that my control supports. In short, there are only two:

  • Display
  • Edit

The first one is the normal state where the UI is not in edit mode, at least not for the personal sections. The second is his counterpart, where the UI is personal edit mode. See the class below.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;namespace Boom.ServerControls {

   public enum PersonalModeDisplay
{
        Display=1
     
, Edit=2
   }
}

PersonalModePanelDesigner.cs

The PersonalModePanelDesigner class will provide the designer instructions on how the render the control at design time. It inherits from ContainerControlDesigner and just override the FrameCaption and FrameStyle properties. See below:

using System.Security.Permissions;
using Microsoft.SharePoint.Security;
using System.Web.UI.Design;
using System.Web.UI.WebControls;
using System.Drawing;
using System.Globalization; 

namespace Boom.ServerControls {

[PermissionSet(SecurityAction.LinkDemand, Name = “FullTrust”), SharePointPermission(SecurityAction.LinkDemand, ObjectModel = true)]
public class PersonalPageModePanelDesigner : ContainerControlDesigner {
   // Fields
   private Style frameStyle;

   // Properties

   public override string FrameCaption {
      [SharePointPermission(SecurityAction.Demand, ObjectModel = true)]
      get {
         return “PersonalModePanelFrame”;
      }
   }

   public override Style FrameStyle
{
   [SharePointPermission(SecurityAction.Demand, ObjectModel = true)]
   get {
      if (this.frameStyle == null) {
         this.frameStyle = new Style();
         this.frameStyle.Font.Name = “Tahoma”;
         this.frameStyle.Font.Size = new FontUnit(“XSmall”, CultureInfo.CurrentUICulture);
         this.frameStyle.BackColor = Color.LightBlue;
         this.frameStyle.ForeColor = Color.Black;
   }

   return this.frameStyle;
}
}
}
}

PersonalModePanel.cs

So, now on to the real code. At this point I might disappoint you, as again, nothing fancy going on in here. First the code:

using System.ComponentModel;
using System.Web.UI;
using System.Web;
using Microsoft.SharePoint.Security;
using System.Web.UI.WebControls;
using System.Security.Permissions;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint;
using System.Web.UI.WebControls.WebParts;
using System;

namespace
Boom.ServerControls
{
   [Designer(typeof(PersonalPageModePanelDesigner))
   , ParseChildren(false)
   , ToolboxData(“<{0}:PersonalModePanel runat=server></{0}:PersonalModePanel>”)
   , AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)
   , SharePointPermission(SecurityAction.InheritanceDemand, ObjectModel = true)
   , AspNetHostingPermission(SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)
   , SharePointPermission(SecurityAction.LinkDemand, ObjectModel = true)]
   public class PersonalModePanel : Panel, INamingContainer, IParserAccessor {
      // Fields
      private bool shouldRender;

      // Methods
      [SharePointPermission(SecurityAction.Demand, ObjectModel = true)]
      protected override void AddParsedSubObject(object obj) {
         this.CalculateShouldRender();
         if (this.shouldRender) {
            base.AddParsedSubObject(obj);
         }
      }

      private
void CalculateShouldRender()
{
         try {
            HttpRequest request = HttpContext.Current.Request;
            if (request.QueryString.Get(“PageView”) == “Personal”) {
               // At least in edit mode for personal sections.
              if (this.PersonalModeDisplay == PersonalModeDisplay.Edit)
                 this.shouldRender = true;
              else
                 this.shouldRender = false;
            }
            else if (this.PersonalModeDisplay == PersonalModeDisplay.Display) {
               this.shouldRender = true;
            }
            else {
               this.shouldRender = false;
            }

            this.Visible = shouldRender;
        }
        catch (Exception ex) {
           this.Visible = true;
        }
        } 

       [SharePointPermission(SecurityAction.Demand, ObjectModel = true)]
    public override void RenderBeginTag(HtmlTextWriter writer) {
       if (!this.SuppressTag) {
          base.RenderBeginTag(writer);
       }
    }

    [SharePointPermission(SecurityAction.Demand, ObjectModel = true)]
    public override void RenderEndTag(HtmlTextWriter writer) {
       if (!this.SuppressTag) {
          base.RenderEndTag(writer);
       }
   }

   // Properties
   [Category(“Appearance”), DefaultValue(1)]
   public PersonalModeDisplay PersonalModeDisplay {
      get {
         object obj2 = this.ViewState[“PersonalModeDisplay”];
         if (obj2 != null) {
            return (PersonalModeDisplay)obj2;
         }
         return PersonalModeDisplay.Edit;
      }
      set {
         this.ViewState[“PersonalModeDisplay”] = value;
      }
   }

   [Category(“Appearance”), DefaultValue(false)]
   public bool SuppressTag {
      get {
         object obj2 = this.ViewState[“RenderTag”];
         return ((obj2 != null) && ((bool)obj2));
      }
      set {
        this.ViewState[“RenderTag”] = value;
      }
   }
}
}

First, in the class attributes we specify the designer for our control that is of type PersonalModePanelDesigner obviously. We also add some toolbox data, which defines the tag that will be rendered by the intellisense in Visual Studio, in this case <{0}:PersonalModePanel>. The ‘{0}’ just indicates that the designer will insert the TagPrefix here that you will set when registering the control. We will do that later. The rest are security headers that I have just taken from the EditModePanel class.

The class further contains several properties PersonalModeDisplay and SuppresTag that will also be provided to the intellisense and are therefore attributes to our control tag. The real code is located in the CalculateShouldRender method, where we define whether or not the contents of the control should be rendered based on the settings of the control.

CalculateShouldRender method

My first approach was to get the Page object of this page and request the WebPartManager to provide the PersonalizationScope of the page. Turns out that requesting this.Page returns null in the stage of the page lifecycle we are in, so that was a dead end. Instead, I used the querystring method where I just look for the PageView=Personal parameter to be present. If so, the contens should be rendered only if the PersonalModeDisplay is set to Edit. In all other cases, it should not render. Finally, I assign the shouldRender variable to the visible property of the class. And we are done!

Deploy and use the code

Now that we have our control, we can use it in our page designs and layouts. Deploy the assembly to your server using the WSP and open a page layout in SharePoint designer. Register the control in the page by providing the following tag at the top of the page:

<%@ Register Tagprefix=”Boom” Namespace=” Boom.ServerControls” Assembly=”Boom.ServerControls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=2847780e0448016d6″ %>

When done, we can insert our control in the page, for example like this:

<Boom:PersonalModePanel runat=”server” PersonalDisplayMode=”Display” SuppressTag=”true”>This is only shown in Display mode</Boom:PersonalModePanel>

<Boom:PersonalModePanel runat=”server” PersonalDisplayMode=”Edit” SuppressTag=”true”>This is only shown in Edit mode</Boom:PersonalModePanel>

 Conclusion

So now we have a control that can show different contents based on the personal edit mode of an end-user. For example, we can provide some more instructions in such a panel that is only shown when he or she enters their personal edit mode. Or we can provide different controls to style and control the editing experience. It is just handy 😉 Let your imagination do the talking and use this wherever you like.

Get the VS solution here.

Thanks for making it this far 😉 Leave some comments if you have time!

Advertisements

One Response to “Personal Edit Mode Panel”

  1. diet said

    diet…

    […]Personal Edit Mode Panel « Patrick's SharePoint Blog[…]…

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: