In any case, even when you find some one knowledgeable you also run into the fact that they may not specify whether they are talking about Sharepoint 2003, 2007 or 2010 (I ONLY deal with Sharepoint 2010 on my blog) or maybe leave off information they deem too complex or too simple. As was the case when I needed to have a custom webpart property that allowed a users to search for a List. I found DOZENS of ways to accomplish this that ranged from super simple (and useless) to absurdly complex. I tried many of these and most did not work properly or how I would expect. MS has several webparts that to do this (i.e. Content Query Web Part), so why is doing it yourself such a mystery?
As some background, for my project I needed a web part that would take a list, read in the rows and items and display this in a branding friendly manner for our publishing sites. As such, I wanted Content Owners to be able to add the web part and select a list they created somewhere in the site for it to use. I called this web part "QuickLinks" so keep that in mind as you read my code.
First off, you should understand a bit about adding custom properties to a web part. Here are a few links I found very helpful:
http://morshemesh.blogspot.com/2011/05/adding-custom-properties-to-visual-web.html
http://www.lamber.info/post/2010/05/21/How-do-I-create-custom-properties-in-Visual-Web-Parts.aspx
http://naimishpandya.wordpress.com/2012/01/12/how-to-add-custom-web-part-properties-to-visual-web-part-in-sharepoint-2010/
Once you have a handle on adding a custom property then a List Picker will not contain many surprises. The main difference is that you have to (for lack of a better term) build your picker before it can be added as a functional control. Even though you are calling a built in tool that MS uses and has available, you have to set the stage and provide some code before you add it. This seems like a little overkill to me, but I guess MS likes to make us developers sweat a little.
Here is my code for the ListPicker. As a note, I pieced this together from a variety of sources. Many of which served other purposes, so please forgive me if there is something weird in there.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Text; | |
using System.Web.UI.WebControls.WebParts; | |
using System.Web.UI.WebControls; | |
using System.Web.UI; | |
using Microsoft.SharePoint; | |
namespace QuickLinks | |
{ | |
public class ListPicker : EditorPart | |
{ | |
private TextBox txtListUrl; | |
private Button _selectList; | |
private String WebPartName = String.Empty; | |
public ListPicker(string webPartID, string webpartname) | |
{ | |
this.ID = "ListPicker" + webPartID; | |
this.Title = "Select a Quick Links Enabled List"; | |
this.WebPartName = webpartname; | |
} | |
protected override void CreateChildControls() | |
{ | |
base.CreateChildControls(); | |
txtListUrl = new TextBox(); | |
//_listUrl.Enabled = false; | |
Controls.Add(txtListUrl); | |
_selectList = new Button(); | |
_selectList.OnClientClick = "javascript:launchPicker();"; | |
_selectList.Text = "..."; | |
Controls.Add(_selectList); | |
Controls.Add(new LiteralControl("<br /><br />")); | |
} | |
public override void SyncChanges() | |
{ | |
EnsureChildControls(); | |
if (WebPartName.Equals("QuickLinks")) | |
{ | |
QuickLinks.QuickLinks webPart = WebPartToEdit as QuickLinks.QuickLinks; | |
if (webPart != null) | |
{ | |
txtListUrl.Text = webPart.qlListProp; | |
} | |
} | |
} | |
public override bool ApplyChanges() | |
{ | |
EnsureChildControls(); | |
if (WebPartName.Equals("QuickLinks")) | |
{ | |
QuickLinks.QuickLinks webPart = WebPartToEdit as QuickLinks.QuickLinks; | |
if (webPart != null) | |
{ | |
webPart.qlListProp = txtListUrl.Text; | |
} | |
} | |
return true; | |
} | |
protected override void OnLoad(EventArgs e) | |
{ | |
base.OnLoad(e); | |
string webLocale = SPContext.Current.Web.Locale.LCID.ToString(); | |
Page.ClientScript.RegisterClientScriptInclude("PickerTreeDialog", string.Format("/_layouts/{0}/PickerTreeDialog.js", webLocale)); | |
RegisterSelectListScript(); | |
} | |
private void RegisterSelectListScript() | |
{ | |
StringBuilder launchPicker = new StringBuilder(); | |
launchPicker.Append("<SCRIPT LANGUAGE='JavaScript' >"); | |
launchPicker.Append("var lastSelectedListSmtPickerId = '';"); | |
launchPicker.Append("function launchPicker() {"); | |
launchPicker.Append(" if (!document.getElementById) return;"); | |
launchPicker.Append(" var listTextBox = document.getElementById('" + txtListUrl.ClientID + "');"); | |
launchPicker.Append(" if (listTextBox == null) return;"); | |
launchPicker.Append(" var serverUrl = '\u002f';"); | |
launchPicker.Append(" var callback = function(results) {"); | |
launchPicker.Append(" if (results == null || results[1] == null || results[3] == null) return;"); | |
launchPicker.Append(" lastSelectedListSmtPickerId = results[0];"); | |
launchPicker.Append(" var listUrl = '/';"); | |
launchPicker.Append(" if (results[3].charAt(0) == '/') results[3] = results[3].substring(1);"); | |
launchPicker.Append(" listUrl = listUrl + results[3];"); | |
launchPicker.Append(" listTextBox.value = listUrl;"); | |
launchPicker.Append(" disablePostbackControls();"); | |
launchPicker.Append(" " + Page.ClientScript.GetPostBackEventReference(txtListUrl, string.Empty) + ";\n"); | |
// __doPostBack('ctl00_MSOTlPn_EditorZone_Edit0g_15f9eea6_e2c8_4a1f_9772_0a32b6394eb2_CBQToolPartshowItemsFromListRadioButton', listTextBox.value); | |
launchPicker.Append(" };"); | |
launchPicker.Append("LaunchPickerTreeDialog('CbqPickerSelectListTitle','CbqPickerSelectListText','websLists','', serverUrl, lastSelectedListSmtPickerId,'','','/_layouts/images/smt_icon.gif','', callback, '', '');"); | |
launchPicker.Append("}"); | |
launchPicker.Append("</SCRIPT>"); | |
if (!Page.ClientScript.IsClientScriptBlockRegistered("launchPicker")) | |
Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "launchPicker", launchPicker.ToString()); | |
} | |
} | |
} |
Now you have your ListPicker ready for use, so we will use the other tricks to add this as a custom property. Next make sure your webpart.cs file defines the ToolboxItem as IWebEditable. I have included my entire QuickLinks.cs file below for an example.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.ComponentModel; | |
using System.Web; | |
using System.Web.UI; | |
using System.Web.UI.WebControls; | |
using System.Web.UI.WebControls.WebParts; | |
using Microsoft.SharePoint; | |
using Microsoft.SharePoint.WebControls; | |
using System.Collections.Generic; | |
namespace QuickLinks.QuickLinks | |
{ | |
[ToolboxItemAttribute(false)] | |
public class QuickLinks : WebPart, IWebEditable | |
{ | |
private string _qlListProp; | |
[Browsable(false)] | |
[Personalizable(PersonalizationScope.Shared)] | |
public string qlListProp | |
{ | |
get { return this._qlListProp; } | |
set { this._qlListProp = value; } | |
} | |
// Visual Studio might automatically update this path when you change the Visual Web Part project item. | |
private const string _ascxPath = @"~/_CONTROLTEMPLATES/QuickLinks/QuickLinks/QuickLinks.ascx"; | |
protected override void CreateChildControls() | |
{ | |
Control control = Page.LoadControl(_ascxPath); | |
Controls.Add(control); | |
} | |
#region IWebEditable Members | |
EditorPartCollection IWebEditable.CreateEditorParts() | |
{ | |
List<EditorPart> editors = new List<EditorPart>(); | |
// Add the base editor parts | |
editors.Add(new ListPicker(this.ID, "QuickLinks")); | |
return new EditorPartCollection(editors); | |
} | |
object IWebEditable.WebBrowsableObject | |
{ | |
get { return this; } | |
} | |
#endregion | |
} | |
} |
Finally you will want to add the few lines to your main webpart code behind to so you can use the custom property. I have a stub of code below to demonstrate how I added it:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace QuickLinks.QuickLinks | |
{ | |
public partial class QuickLinksUserControl : UserControl | |
{ | |
// For Custom Properties | |
public QuickLinks WebPart { get; set; } | |
protected override void OnPreRender(EventArgs e) | |
{ | |
base.OnPreRender(e); | |
// For Custom Properties | |
this.WebPart = this.Parent as QuickLinks; | |
// Rest of your code | |
} | |
} | |
} |
If this works for you like it worked for me, you just spent less time adding the List Picker than searching for how to do it. One thing that bothers me is I have seen this code for 2007 and it is not much different, so hopefully this is a supported way of doing this. However, if it works maybe its worth the risk.
Happy Sharepointing!
Nice post....I would like to point out that when creating Editor part, implementing IWebEditable is one way of creating editor parts. The other way is to just override the CreateEditorParts method.
ReplyDeleteThanks for the comment, Suhas. Any insight into the differences between these methods or benefits to using one vs the other? In looking briefly at other postings about them they seem very similar in practice.
DeleteThanks again.