While I was working on my MOSS application we have a special requirement to replace OOB people picker with custom people picker. Replacing the OOB people picker is a tidious process. I am going to outline the steps which needs to be taken care to replace OOB people picker with custom people picker in my next blog.
The rich user interface provided by people picker can be used in many ways with in sharepoint environment, not just for picking people from user repository.
For instance, if you want to provide user interface, which displays all the faciliies from which user has to select one or more items then you can immediately think of checkbox list in case of multi select where as dropdown list in case of single select. It won’t be a good user experience with 100’s of records.
Let us discuss how People Picker kind of control will provide better user experience. Let us assume that you have “Facility” entity in your sql server database with two columns FacilityCode and FacilityName.
Let us assume that this table contains 1000 records. If we create custom Facility Picker you need not display all the 1000 records from which user has to select. If user knows a facility code then he/she can type in the facility code and click on the check names button to resolve. If user wants to browse through the facility list then click on the browse button to select from the list.
Let us start building the Facility Picker control by inheriting from three different classes which are part of “Microsoft.SharePoint.WebControls” namespace.
create a class which inherits from “EntityEditorWithPicker” and name it as FacilityPickerEntityEditor as shown below. Most of the code is self explainatory. I will highlight in the areas where it is required.
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint;
using System.Configuration;
namespace CustomPickers.Controls
{
public class FacilityPickerEntityEditor : EntityEditorWithPicker
{
public DataSet dsFacility = null;
public DataRow drSelectedFacility = null;
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
// FacilityPickerPickerDialog class is one the three class which we // are going to build today
PickerDialogType = typeof(FacilityPickerPickerDialog);
// I have used “;” to sperate the entity selection.
this.EntitySeparator = Convert.ToChar(";");
// I am restricting to single select. You can change to “true” to
// enable multiselect
this.MultiSelect = false;
}
public override PickerEntity ValidateEntity(PickerEntity needsValidation)
{
needsValidation.IsResolved = false;
string validateKey = needsValidation.Key.ToString();
// GetFacilityInfoByCode method will take the key entered by the // user and resolve againist the
dsFacility = GetFacilityInfoByCode(validateKey);
if (ds != null && ds.Tables.Count > 0 && ds.Tables[0].Rows.Count > 0)
{
dr = ds.Tables[0].Rows[0];
needsValidation.DisplayText = dr ["FacilityName"].ToString().Trim();
needsValidation.IsResolved = true;
}
return needsValidation;
}
}
Protected DataSet GetFacilityInfoByCode(string facilityCode)
{
// Your code goes here to execute the stored procedure GetFacilityInfoByCode
/*
CREATE PROCEDURE [dbo].[GetFacilityInfoByCode]
(
@FacilityCode nvarchar(50)
)
AS
BEGIN
Select FacilityCode, FacilityName
From Facility
Where FacilityCode = @FacilityCode
END
*/
}
}
create the second class which inherits from “SimpleQueryControl” and name it as FacilityPickerQueryControl as shown below.
using System;
using System.Collections.Generic;
using System.Data;
using System.Text;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint;
using System.Configuration;
namespace CustomPickers.Controls
{
public class FacilityPickerQueryControl: SimpleQueryControl
{
public FacilityPickerQueryControl ()
{
Load += FacilityPickerQueryControl_Load;
}
void FacilityPickerQueryControl_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
EnsureChildControls();
mColumnList.Items.Add("FacilityCode");
mColumnList.Items.Add("FacilityName");
}
}
protected override int IssueQuery(string search, string groupName, int pageIndex, int pageSize)
{
DataSet ds = null;
try
{
// This condition will be executed when you select //FacilityCode from the dropdown and enter string for search
if (groupName == "FacilityCode")
{
ds = GetFacilityInfoByCodeStringsearch(search);
}
// This condition will be executed when you select //FacilityName from the dropdown and enter string for search
else if (groupName == "FacilityName")
{
ds = GetFacilityInfoByNameStringSearch(search);
}
if (ds.Tables[0] != null)
{
DataTable dt;
dt = ds.Tables[0];
PickerDialog.Results = dt;
PickerDialog.ResultControl.PageSize = dt.Rows.Count;
return dt.Rows.Count;
}
else
{
return 0;
}
}
catch(Exception ex)
{
throw (ex);
}
}
public override PickerEntity GetEntity(DataRow dr)
{
PickerEntity entity = new PickerEntity();
try
{
entity.DisplayText = "" + dr["FacilityName"].ToString().Trim() ;
entity.Key = dr["FacilityCode"].ToString();
entity.Description = "" + dr["FacilityName"].ToString().Trim();
entity.IsResolved = true;
}
catch (Exception ex)
{
throw (ex);
}
return entity;
}
}
protected DataSet GetFacilityInfoByCodeStringsearch (string facilityCode)
{
// Your code to execute the stored procedure GetFacilityInfoByCodeStringsearch
/*
CREATE PROCEDURE [dbo].[GetFacilityInfoByCodeStringSearch]
(
@FacilityCode nvarchar(50)
)
AS
BEGIN
Select FacilityCode, FacilityName
From Facility
Where FacilityCode Like '%' + @FacilityCode + '%'
END
*/
}
protected DataSet GetFacilityInfoByNameStringSearch (string facilityName)
{
// Your code to execute the stored procedure GetFacilityInfoByNameStringSearch
/*
CREATE PROCEDURE [dbo].[GetFacilityInfoByNameStringSearch]
(
@FacilityName nvarchar(255)
)
AS
BEGIN
Select FacilityCode, FacilityName
From Facility
Where FacilityName Like '%' + @FacilityName + '%'
END
*/
}
}
create the third class which inherits from “PickerDialog” and name it as FacilityPickerDialog as shown below.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Data;
using Microsoft.SharePoint.WebControls;
namespace CustomPickers.Controls
{
public class FacilityPickerDialog : PickerDialog
{
public FacilityPickerDialog()
: base(new FacilityPickerQueryControl(), new TableResultControl(), new FacilityPickerEntityEditor ())
{
ArrayList columnDisplayNames = ((TableResultControl)base.ResultControl).ColumnDisplayNames;
columnDisplayNames.Clear();
columnDisplayNames.Add("Facility Name");
columnDisplayNames.Add("Facility Code");
ArrayList columnNames = ((TableResultControl)base.ResultControl).ColumnNames;
columnNames.Clear();
columnNames.Add("FacilityCode");
columnNames.Add("FacilityName");
ArrayList columnWidths = ((TableResultControl)base.ResultControl).ColumnWidths;
columnWidths.Clear();
columnWidths.Add("40%");
columnWidths.Add("60%");
}
}
}
After you build Facility Picker control you have to add this assembly to the GAC and add it to safecontrols with in web.config file.
If everything goes well it is time to add this control to ASPX page and test it.
The Following Register directive needs to be added to the ASPX page
<%@ Register Assembly=" CustomPickers.Controls" Namespace=" CustomPickers.Controls" TagPrefix="PickerControls" %>
and following markup which goes into the ASPX page
< PickerControls: FacilityPickerEntityEditor ID=" FacilityPickerEntityEditor1" width="50%" runat="server" />
Questions and comments are welcome!
Thanks!!