Anything Picker for SharePoint 2010

We are all familiar with the people picker used in SharePoint web parts and application pages to find and select single or multi users from AD or any form authentication provider. The control is actually built to inherit from a more general purpose control named “EntityEditorWithPicker”.

I will show how you can build a picker from any searchable source. The particular demo is for employees in a SQL table.

I learnt how to do this from

So the steps to incorporate the custom control in SharePoint web parts and pages are:

  1. Create a class file in the same project as the web parts and in it, Extend the 3 classes
    1. public class EmployeeEditor : EntityEditorWithPicker //This will be the reusable control
    2. CustomQueryControl : SimpleQueryControl //settings for the popup control
    3. public class CustomPickerDialog : PickerDialog // settings for the tabular results show
  2. In the “CustomQueryControl” class we can customize the popup dialog with several “search by” options. I used Name and job title but based on the context of the usage, it can be anything. Each “search by” will need its own search method but the results should be the same columns. In my demo it is the ID of the employee, his full name and job title.
  3. The CustomPickerDialog class is just settings for the tabular results to show columns names and width.
  4. The EmployeeEditor class is where most of the work is done. It has methods for search unique or lists and determine entries validation. There is also mapping of the results fields to the entity fields (key, display text and description. I chose the employee ID to be the key
  5. Once the classes are generated and built, the control can be used in web part and pages code like any web control. private EmployeeEditor eeEmployeeToFind = new EmployeeEditor(); off course all the attributes of the base are available. For example, I used MultiSelect to allow single or multiple results.
  6. Since the control is not managed by the SharePoint’s project template, it will not get a “Safe control” line in the web.config file. And if you don’t add it yourself, you get:
    1. VS2010 will make these web.config entries
      1. <SafeControl Assembly=”Peters.Wirtz.HR.WebPartsI2, Version=, Culture=neutral, PublicKeyToken=58b09c82ceb21b3d” Namespace=”Peters.Wirtz.HR.WebPartsI2.MultiEmployeeEdit” TypeName=”*” Safe=”True” SafeAgainstScript=”True” />
      2. <SafeControl Assembly=”Peters.Wirtz.HR.WebPartsI2, Version=, Culture=neutral, PublicKeyToken=58b09c82ceb21b3d” Namespace=”Peters.Wirtz.HR.WebPartsI2.SearchEmployee” TypeName=”*” Safe=”True” SafeAgainstScript=”False” />
      3. <SafeControl Assembly=”Peters.Wirtz.HR.WebPartsI2, Version=, Culture=neutral, PublicKeyToken=58b09c82ceb21b3d” Namespace=”Peters.Wirtz.HR.WebPartsI2.EditEmployee” TypeName=”*” Safe=”True” SafeAgainstScript=”False” />
      4. <SafeControl Assembly=”Peters.Wirtz.HR.WebPartsI2, Version=, Culture=neutral, PublicKeyToken=58b09c82ceb21b3d” Namespace=”Peters.Wirtz.HR.WebPartsI2.TerminateEmployee” TypeName=”*” Safe=”True” SafeAgainstScript=”False” />
      5. <SafeControl Assembly=”Peters.Wirtz.HR.WebPartsI2, Version=, Culture=neutral, PublicKeyToken=58b09c82ceb21b3d” Namespace=”Peters.Wirtz.HR.WebPartsI2.TransferEmployee” TypeName=”*” Safe=”True” SafeAgainstScript=”False” />
      6. </SafeControls>
  7. You need to add:
    1. <SafeControl Assembly=”Peters.Wirtz.HR.WebPartsI2, Version=, Culture=neutral, PublicKeyToken=58b09c82ceb21b3d” Namespace=”Peters.Wirtz.HR.WebPartsI2″ TypeName=”*” Safe=”True” SafeAgainstScript=”False” />
  8. Off course replace “Peters.Wirtz.HR.WebPartsI2” with your namespace
  9. Here is the code :
using System; using System.Linq; using System.Collections; using System.Collections.Generic; using System.Text; using Microsoft.SharePoint.WebControls; using System.Data; using Microsoft.SharePoint;
namespace Peters.Wirtz.HR.WebPartsI2 {     // delegate declaration     public delegate void WasValidatedHandler(object sender, EmployeeArgs e);       public class EmployeeEditor : EntityEditorWithPicker  //This will be the reusable control     {         public string FilteredByCompany { get; set; }         // event declaration         public event WasValidatedHandler WasValidated;
protected override void OnInit(EventArgs e)         {             base.OnInit(e);             PickerDialogType = typeof(CustomPickerDialog);         }         public override PickerEntity ValidateEntity(PickerEntity entity)  // Find exact match to entity.DisplayText         {             if (entity.IsResolved) //Was found before             {                 EmployeeArgs ea = new EmployeeArgs(entity.Key);                 return entity;             }             if (!string.IsNullOrEmpty(entity.DisplayText))             {                 //————My database search—————————-                 HRDataDataContext hr = new HRDataDataContext(SPContext.Current.Web.GetProperty(“HRConnectionString”).ToString());                 var employee = from x in hr.EmployeeMasters where (x.FirstName + ” ” + x.LastName).Equals(entity.DisplayText) select x;                 if (employee.Count() > 0)                 {                     entity.DisplayText = employee.First().FirstName + ” ” + employee.First().LastName;                     entity.Key = employee.First().ID.ToString();                     entity.IsResolved = true;                       //Mark as found                     EmployeeArgs ea = new EmployeeArgs(entity.Key);                 }             }             return entity;         }
protected override PickerEntity[] ResolveErrorBySearch(string unresolvedText) // find many close Machs         {             //————My database search ( Where xxxx- like ‘%the text%’————————–             HRDataDataContext hr = new HRDataDataContext(SPContext.Current.Web.GetProperty(“HRConnectionString”).ToString());             var matches = from x in hr.EmployeeMasters                           where (x.FirstName + ” ” + x.LastName).Contains(unresolvedText)                           orderby (x.FirstName + ” ” + x.LastName)                           select new PickerEntity                           {                               Key = x.ID.ToString(),                               DisplayText = x.FirstName + ” ” + x.LastName,                               Description = x.JobTitle,                               IsResolved = true,                           };             if (matches.Count() == 0)                 return null;             return matches.ToArray();         }
public string CommaSeparatedEmployees         {             get             {                 StringBuilder sb = new StringBuilder();                 foreach (PickerEntity entity in this.ResolvedEntities)                 {                     if (sb.Length > 0)                         sb.Append(“, “);                     sb.Append(entity.Key);                 }                 return sb.ToString();             }             set             {                 this.SetEmployees(value);             }         }
public void SetEmployees(string commaSeparatedIds) //Find By the IDs (keys) of the selcted items         {             if (!string.IsNullOrEmpty(commaSeparatedIds))             {                 string[] EmployeeIDs = commaSeparatedIds.Split(‘,’);                 if (!this.MultiSelect)                     EmployeeIDs = EmployeeIDs.Take(1).ToArray();                 ArrayList entities = new ArrayList();                 HRDataDataContext hr = new HRDataDataContext(SPContext.Current.Web.GetProperty(“HRConnectionString”).ToString());                 var exactMatches = from x in hr.EmployeeMasters where EmployeeIDs.Contains(x.ID.ToString()) select x;                 foreach (var employee in exactMatches)                 {                     PickerEntity entity = new PickerEntity();                     entity.Key = employee.ID.ToString();                     entity.DisplayText = employee.FirstName + ” ” + employee.LastName;                     entity.Description = employee.JobTitle;                     entity.IsResolved = true;                     entities.Add(entity);                 }                 this.UpdateEntities(entities);                 this.Validate();             }             else             {                 this.UpdateEntities(new ArrayList());                 this.Validate();             }         }
protected virtual void OnValidate(EmployeeArgs e)         {             WasValidatedHandler handler = WasValidated;             if (handler != null)             {                 // Invokes the delegates.                 handler(this, e);             }         }
public class CustomQueryControl : SimpleQueryControl  //settings for the popup control     {         public CustomQueryControl()         {             Load += CustomQueryControl_Load;         }
void CustomQueryControl_Load(object sender, EventArgs e)         {             if (!Page.IsPostBack)             {                 EnsureChildControls();                 mColumnList.Items.Add(“Name”);              //Here can determine the “Search by entities” you want to provide                 mColumnList.Items.Add(“Job Title”);         // You can have as many as you can figure searches for             }         }
protected override int IssueQuery(string search, string groupName, int pageIndex, int pageSize)         {             DataTable employeeTable = GetEmployeeTable(search, groupName);             PickerDialog.Results = employeeTable;             PickerDialog.ResultControl.PageSize = employeeTable.Rows.Count;             return employeeTable.Rows.Count;         }
private DataTable GetEmployeeTable(string search, string groupName)         {             DataTable dummyTable = new DataTable();             dummyTable.Columns.Add(“DBID”);             dummyTable.Columns.Add(“Name”);             dummyTable.Columns.Add(“Job Title”);             //————My database search—————————-             string connString = SPContext.Current.Web.GetProperty(“HRConnectionString”).ToString();             HRDataDataContext hr = new HRDataDataContext(connString);
// here you supply the search statement based on the user’s selection             var employee = (groupName == “Name”) ?                 from x in hr.EmployeeMasters where (x.FirstName + ” ” + x.LastName).Contains(search) select x :                 from x in hr.EmployeeMasters where (x.JobTitle).Contains(search) select x;
foreach (var item in employee)             {                 DataRow row = dummyTable.NewRow();                 row[“DBID”] = item.ID;                 row[“Name”] = item.FirstName + ” ” + item.LastName;                 row[“Job Title”] = item.JobTitle;                 dummyTable.Rows.Add(row);             }
return dummyTable;         }
public override PickerEntity GetEntity(DataRow dr)      //Here you match the entity’s fields to the data you want to use.         {             PickerEntity entity = new PickerEntity();             entity.DisplayText = dr[“Name”].ToString();         //I chose the employee full name to be the Display text             entity.Key = dr[“DBID”].ToString();                 //I chose the employee ID to be the key             entity.Description = dr[“Job Title”].ToString();             entity.IsResolved = true;                           // if it was found, no need to validate again so it is marked IsResolved             return entity;         }     }
public class CustomPickerDialog : PickerDialog     // settings for the tabular results show     {         public CustomPickerDialog()             : base(new CustomQueryControl(), new TableResultControl(), new EmployeeEditor())         {             ArrayList columnDisplayNames = ((TableResultControl)base.ResultControl).ColumnDisplayNames;             columnDisplayNames.Clear();             columnDisplayNames.Add(“DBID”);             columnDisplayNames.Add(“Name”);             columnDisplayNames.Add(“Job Title”);             ArrayList columnNames = ((TableResultControl)base.ResultControl).ColumnNames;             columnNames.Clear();             columnNames.Add(“DBID”);             columnNames.Add(“Name”);             columnNames.Add(“Job Title”);             ArrayList columnWidths = ((TableResultControl)base.ResultControl).ColumnWidths;             columnWidths.Clear();             columnWidths.Add(“0%”);             columnWidths.Add(“30%”);             columnWidths.Add(“70%”);         }     }
//// custom attributes     public class EmployeeArgs : System.EventArgs     {         private string key;         public EmployeeArgs(string m)         {             this.key = m;         }         public string Key         {             get { return key; }         }     }

About Ofer Gal

This entry was posted in SharePoint Development. Bookmark the permalink.

Leave a Reply

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

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

Google+ photo

You are commenting using your Google+ 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 )

Connecting to %s