Web Parts. Custom editor part (even more - custom visual editor part) and web parts properties.

by Kai 19. June 2011 19:10

Hi 2 all!
I continue to write posts about using and programming web parts. Here listed all topics about web parts:

In this post I will give a little sample about how to use web parts properties and how to write custom editor part. Let’s start. 

Every web part contain a set of  base properties, you have the opportunity to create custom properties.  Web part property is a object that user can customize. Every property has a set of attributes, which associated with it. This attributes describe property settings, such as name, description, and others. Let’s see the declaration of a simple web part property:

[WebBrowsable(true),
 WebDisplayName("Greetings"),
 WebDescription("user greetings"),
 Category("Custom settings"),
 Personalizable(PersonalizationScope.User)]
public string Greetings
{
	get;
	set;
}

Property has several attributes:
    -WebBrowsable attribute is responsible for displaying property in a editor part, if you pass true to constructor it means that this property will be displayed in editor part, otherwise no.
    -WebDisplayName is a display name of your custom property that appear (if WebBrowsable(true)) in editor part.
    -WebDescription is a tool tip message that will be displayed when you hover over an property in editor UI
    -Category is a name of group where your custom property will be display. For example, if you not set this attribute, your custom property will be displayed in “Miscellaneous”  group:

If you set this attribute, you will able to see something like this:

-Personalizable is a significant attribute. What is mean PersonalizationScope? When you pass PersonalizationScope.User in attribute constructor, it means that all changes in this web part on this page will be applied only for current user. SharePoint store personalizable properties’ values in content db, and they will be applied only for user that made it. Otherwise, if you pass PersonalizationScope.Shared to constructor all, all changes that current user make will be visible for all other site users. You can read a little bit more about personalization here.

As you can already seen in image, I’ve created some custom properties that displaying in editor part. Editor part you can open by clicking “Edit web part” in the top right corner with an arrow. Different types of custom properties renders in editor part by differently. DateTime, string, int, float properties types render as textboxes, bool type as checkbox, and enum as drop-down. Code for this properties:

[WebBrowsable(true),
 WebDisplayName("Page Size"),
 WebDescription("set the page size"),
 Category("Custom settings"),
 Personalizable(PersonalizationScope.User)]
public int PageSize
{
	get; set;
}

[WebBrowsable(true),
 WebDisplayName("Editable"),
 Category("Custom settings"),
 WebDescription("settings that allow you to edit web part"),
 Personalizable(PersonalizationScope.User)]
public bool Editable
{
	get;
	set;
}

[WebBrowsable(true),
 WebDisplayName("Greetings"),
 WebDescription("user greetings"),
 Category("Custom settings"),
 Personalizable(PersonalizationScope.User)]
public string Greetings
{
	get;
	set;
}

[WebBrowsable(true),
 WebDisplayName("CurrentDate"),
 Category("Custom settings"),
 WebDescription("gets the current date"),
 Personalizable(PersonalizationScope.User)]
public DateTime CurrentDate
{
	get;
	set;
}

[WebBrowsable(true),
 WebDisplayName("Season"),
 WebDescription("gets the current season"),
 Category("Custom settings"),
 Personalizable(PersonalizationScope.User)]
public Seasons Season
{
	get;
	set;
}

How to set default values for your custom properties? You may do it through .webpart file. In “property” section you can assign default values:

<properties>
<property name="Greetings" type="string">Hi there!</property>
<property name="Season" type="CustomEditorPart.WebParts.LinksStore.Seasons, CustomEditorPart, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ef7884be06e418fc">Summer</property>
<property name="PageSize" type="int">4</property>
<property name="Editable" type="bool">True</property>
<property name="CurrentDate" type="datetime">06/19/2011 18:27:24</property>
   <!-- some other properties -->
</properties>

You can this is a little tricky to assign value for enum – in type attribute you must specify full four-part name of assembly. As soon as you declare custom property (with WebBrowsable(true) attribute), it appear in a editor part. Ok, we can use primitive types as type of custom property, but can we use something like this:

[WebBrowsable(true),
 WebDisplayName("Custom class"),
 WebDescription("custom class descrtiption"),
 Category("Custom settings"),
 Personalizable(PersonalizationScope.User)]
public MyClass Settings
{
	get;
	set;
}

One advice – you can use string to serialize your class and store your object in string web part property, another way – I don’t know. May be write custom personalization provider, if it is possible for SharePoint at all. If you know answer, please, tell me, it rather interesting question.
In addition you can use List<string> as personalizable data:

[WebBrowsable(true),
 WebDisplayName("Settings"),
 WebDescription("some settings store"),
 Category("Custom settings"),
 Personalizable(PersonalizationScope.User)]
public List<string> Settings
{
	get;
	set;
}

It works great, although it never renders in editor part (even if WebBrowsable(true)).

This list of string I use in my custom editor part. So, let’s examine how to write custom editor part.
Ok, the scenario: user wants to store in web part any settings, which presented as strings (it may be links for example). User must have ability to add or delete links in web part editor part, and this collection of links must be personalized for user. Of course you can use simple string property for this purpose and separate each link with predefined template (like ;# in SharePoint)and parse it dynamically. But we are not looking for easy ways and will use List<string> as personalizable data.

First of all we need to create custom editor part class – it must inherit from class EditorPart:

public class LinksStoreEditorPart : EditorPart

As mentioned in post title we will use visual editor part, that’s why in override CreateChildControls() we load our user control for editor part and add it to controls collection:

private const string PathToEditorUserControl = "~/_controltemplates/CustomEditorPartSample/LinksStoreEditorUserControl.ascx";
private WebPartEditorControl _editorControl;

protected override void CreateChildControls()
{
	_editorControl = (WebPartEditorControl) Page.LoadControl(PathToEditorUserControl);
	Controls.Add(_editorControl);
}

LinksStoreEditorUserControl is responsible to render list of string and allow adding and deletion of it. I use asp.net repeater control to render strings and image buttons to delete strings. LinksStoreEditorUserControl has a Titles property that perform data bind for repeater control:

public List<string> Titles
{
	set
	{
		if (value == null) return;
		rptLinks.DataSource = value.Select(v => new LinkEntity{Title = v}).ToList();
		rptLinks.DataBind();
	}
}

So, when we set Title property it actually perform data bind for asp.net repeater. Other code in control is responsible for adding new strings and deletion. I skip this for brevity. All code for LinksStoreEditorUserControl you can find in attachments to post. 

Let’s back to the LinksStoreEditorPart class. It has two significant for editor part methods - ApplyChanges() and SyncChanges(). The first method is fire when we need to save changes in web part’s personalizable properties and the second fire when you open editor part and need to transfer settings from web part’s properties to custom editor part. The code in methods:

//transfer settings from editor part to our web part
public override bool ApplyChanges()
{
	EnsureChildControls();
	var wp = (LinksStoreWebPart) WebPartToEdit;
	wp.Settings = _editorControl.GetData();
	return true;
}

//transfer settings from web part to editor part
public override void SyncChanges()
{
	EnsureChildControls();
	var wp = (LinksStoreWebPart)WebPartToEdit;
	_editorControl.Titles = wp.Settings;
}

Me must call EnsureChildControls() to be sure that our user control (_editorControl) already initialized and we can use it properties. In ApplyChanges() I get instances of current web part using WebPartToEdit base property of EditorPart class. Method GetData() returns List<string> from repeater control, then I assign this returned data to web part’s Settings property. That is, I save custom personalize data to web part. This data will be stored in content db. In SyncChanges() I must init custom editor part with data from web part, this is the reverse process. I copy settings from web part to editor part.
The last step is let web part to know to use our custom editor part. This makes through override CreateEditorParts() method (in web part clss):

public override EditorPartCollection CreateEditorParts()
{
	var editorParts = new List<EditorPart>(1);
	var editor = new LinksStoreEditorPart();
	editor.ID = ID + "LinksStoreEditorPart"; 
	editor.Title = "Links Store custom editor part.";
	editorParts.Add(editor);
	return new EditorPartCollection(base.CreateEditorParts(), editorParts);
}

One thing I want mention. You must set to custom editor part object (editor in my way) unique ID, if you don’t do so you get System.InvalidOperationException: EditorPart does not have an ID, so it is required to set ID for custom editor part. After that you can use you custom editor part. My custom editor part looks like follows:

What my web part actually do? It simply display it’s custom personalizable properties to make sure that they are worked as expected. I omitted some code for shortness, you can download full working project using link below the post.
How can you use List<string> personalizable data? For example Quick links web part – user store some useful links in a page for inner recourses of site. Settings for links you can store and control through custom editor part. Every user can set up required for he (or she) links, because your custom property will have personalization scope user.
Sample project you can download here (21.26 kb)

Sorry for my English.

Tags: ,

SharePoint | Web Parts

Pingbacks and trackbacks (1)+

Add comment

biuquote
  • Comment
  • Preview
Loading