RSS

Updating web part properties through the layout in SharePoint 2010


Published by Eugene Martynov
Publish date: 10/27/2011 12:31:12 PM

I do not like the standard web part editor (Edit Web Part) in SharePoint 2010. It breaks page layout, it makes post back refreshing the whole page and so on… In this article I want to show how to update web part properties through the web part representation without web part editor.

Let’s make the following functionality:

-          Content manager adds web part to a page;

-          Content manager opens web part editor (Edit Web Part) and adds the list of values;

-          User, that has not privileges to edit the web part, chooses the values from the list using the frontend interface.

-          The Web Part saves values chosen by the users.

Create the new SharePoint 2010 project and add a visual web part.

The web part class overrides CreateEditorParts to implement custom Editor Part so content managers can add the list of values:

public override EditorPartCollection CreateEditorParts()
		{
			var editors = new List {new ConfigEditor {ID = "ConfigEditor"}};
			return new EditorPartCollection(editors);
		}

Values are stored in the web part ConfigList property:

[Personalizable(PersonalizationScope.Shared)]
public List ConfigList { get; set; }

The full code listed below:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Web.UI.WebControls.WebParts;
using Microsoft.SharePoint;

namespace SharePointProject1.VisualWebPart2
{
	[ToolboxItem(false)]
	public class VisualWebPart2 : WebPart
	{
		private const string AscxPath =
			@"~/_CONTROLTEMPLATES/SharePointProject1/VisualWebPart2/VisualWebPart2UserControl.ascx";

		private VisualWebPart2UserControl m_control;

		[Personalizable(PersonalizationScope.Shared)]
		public List ConfigList { get; set; }

		[Personalizable(PersonalizationScope.Shared)]
		public string ConfigValue { get; set; }

		protected override void CreateChildControls()
		{
			m_control = (VisualWebPart2UserControl) Page.LoadControl(AscxPath);
			if (ConfigList != null)
				m_control.ConfigList = ConfigList;

			if (ConfigValue != null)
				m_control.ConfigValue = ConfigValue;

			Controls.Add(m_control);

			SPSecurity.RunWithElevatedPrivileges(UpdateConfigProperty);
		}

		protected void UpdateConfigProperty()
		{
			if (m_control != null)
			{
				if (m_control.ConfigValue != null)
				{
					ConfigValue = m_control.ConfigValue;
					SetPersonalizationDirty();
				}
			}
		}

		public override EditorPartCollection CreateEditorParts()
		{
			var editors = new List {new ConfigEditor {ID = "ConfigEditor"}};
			return new EditorPartCollection(editors);
		}
	}
} 

ConfigValue property is used to keep the selected value from the list (ConfigList property).

CreateChildControls method perform three actions:

  1. Pass property values to the user control;
  2. Add the control;
  3. Update ConfigValue property if it was modified. Remark: do not forget to call SetPersonalizationDirty method after the property was updated. RunWithElevatedPrivileges method is optional according to your privileges.

The code of the custom Editor Part class:

using System.Linq;
using System.Web.UI.WebControls.WebParts;


namespace SharePointProject1.VisualWebPart2
{
	public class ConfigEditor : EditorPart
	{
		private const string AscxPath = @"~/_CONTROLTEMPLATES/SharePointProject1/VisualWebPart2/UserControl1.ascx";
		private UserControl1 m_control;

		protected override void CreateChildControls()
		{
			m_control = (UserControl1) Page.LoadControl(AscxPath);
			Controls.Add(m_control);
		}

		public override bool ApplyChanges()
		{
			EnsureChildControls();
			var part = WebPartToEdit as VisualWebPart2;
			if (part == null)
				return false;

			part.ConfigList = m_control.ConfigList.Split(",".ToCharArray()).ToList();
			
			return true;
		}

		public override void SyncChanges()
		{
			EnsureChildControls();
			var part = WebPartToEdit as VisualWebPart2;
			if (part != null && part.ConfigList != null)
			{
				string valuesFromWp = part.ConfigList.Aggregate(string.Empty, (current, textMsg) => current + (textMsg + ","));
				m_control.ConfigList = valuesFromWp.Remove(valuesFromWp.Length - 1, 1);
			}
		}
	}
} 

In the ConfigEditor class we have two methods: ApplyChanges and SyncChanges. ApplyChanges read values from text area inside the custom Editor Part and saves them when user applies changes. SyncChanges reads saved values and displays it inside the custom Editor Part when user opens web part editor (Edit Web Part).

The user control for the custom Editor Part is simple. You can use server control classes instead.

.ascx:

<%@ Assembly Name="$SharePoint.Project.AssemblyFullName$" %>
<%@ Assembly Name="Microsoft.Web.CommandUI, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="UserControl1.ascx.cs" Inherits="SharePointProject1.VisualWebPart2.UserControl1" %>


<textarea id="TextArea1" style="width: 300px; height: 100px;" runat="server">
</textarea> 

.cs:

using System.Web.UI;

namespace SharePointProject1.VisualWebPart2
{
	public partial class UserControl1 : UserControl
	{
		public string ConfigList
		{
			get { return TextArea1.InnerText; }
			set { TextArea1.InnerText = value; }
		}
	}
} 

The user control for the web part implements Ajax:

.ascx:

<%@ Assembly Name="$SharePoint.Project.AssemblyFullName$" %>
<%@ Assembly Name="Microsoft.Web.CommandUI, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="VisualWebPart2UserControl.ascx.cs" Inherits="SharePointProject1.VisualWebPart2.VisualWebPart2UserControl" %>

<script src="http://code.jquery.com/jquery-1.6.4.min.js" type="text/javascript"> </script>

<fieldset id="myFieldset">
<%if (ConfigList != null)
  { %>
	<% foreach (string item in ConfigList)
	{%>
			<input type="radio" id="<%=item%>" name="config" value="<%=item%>" 
			
			<%if (ConfigValue == item)
				{ %> checked="checked"<% } %> /> 
			
			<%=item%>
			<br/>			
	<% }
  }%>
	<br/>
	<input type="button" id="button" name="button" title="Save" value="Save" />
</fieldset>


<script type="text/javascript">

	$("#button").click(function () {
		var settingsToSend = $("#myFieldset").serialize();
		var requestDigest = $.param({ "__REQUESTDIGEST": $("#__REQUESTDIGEST").val() });
		
		$.ajax({
			type: 'POST',
			url: '<% =HttpContext.Current.Request.Url.AbsolutePath%>',
			data: settingsToSend + "&" + requestDigest,
			success: function () {
				alert("Config has been saved!");
			}
		});
	});
</script> 

.cs:

using System;
using System.Collections.Generic;
using System.Web.UI;

namespace SharePointProject1.VisualWebPart2
{
	public partial class VisualWebPart2UserControl : UserControl
	{
		public List ConfigList { get; set; }
		public string ConfigValue { get; set; }

		protected void Page_Init(object sender, EventArgs e)
		{
			if (Request.Headers["X-Requested-With"] == "XMLHttpRequest")
			{
				ConfigValue = Request.Params["config"];
			}
		}
	}
}

This parameter is very important and without it SharePoint will not save values provided by users. SharePoint uses this hidden field to validate the page.

var requestDigest = $.param({ "__REQUESTDIGEST": $("#__REQUESTDIGEST").val() });

The summary:

Updating web part properties through the layout in SharePoint 2010

 

Special thanks to Vitaly Pavluk for his help with the article.


Tags: asp.net , sharepoint 2010 , ajax , requestdigest

Back to Home
blog comments powered by Disqus

Copyright © 2011 Eugene Martynov, CSS Templates by Inf Design