Skip to main content Home Help (new window) Rajesh Satluri
Go Search
Home
Blogs
Company
Products
Services
Current News
BinaryWave Announces Release of Sonar Standard Version 1.1
Upcoming Events
Other Blogs
There are no items in this list.
Home > Blogs > Rajesh Satluri



Replacing People Picker with Custom People Picker

As I mentioned in my earlier blog item “Custom Picker Control” that I am going to post information on replacing OOB people picker with a custom people picker with custom data source. Here is the information.

Integration of custom people picker control with site definition

·         The custom people picker control cannot be integrated with the custom site definition. The OOB people picker control has been used in several application pages (Layout pages) which cannot be replaced just by integrating the control with the site definition.

·         Moreover in Sharepoint site definitions it’s not possible to integrate any control to replace the OOB controls

Customizing the Application Pages to replace the OOB people picker control with the custom people picker

·         There are several application pages in which the OOB people picker control is used. For Ex peoples.aspx, Groups.aspx, aclinv.aspx… etc. The workflow pages also reside under the application pages category.

·         If you want to replace the people picker in these pages you need to create custom application pages by copying the respective OOB pages and need to replace the OOB people picker with the custom people picker control.

·         To redirect the users to your custom application pages you will end up in customizing the navigation.

·         When you are replacing the control then you need to change the code behind for the server related events of the pages so that the sharepoint reads data from your custom control and does not look for the OOB people picker control. Unfortunately, we can't disassemble Microsoft.Sharepoint.Applicationpages to read MS mind. :(

·         It is going to be big development effort depends on how many custom application pages you creates to implement the custom people picker control.

Customizing the Item form pages (NewForm.aspx, EditForm.aspx, DispForm.aspx… Etc) with the custom people picker

·         The most critical part of replacing the custom people picker comes with customizing the item form pages. Unlike the other application pages item form pages are rendered dynamically and the number of fields and the controls related to the list is determined dynamically on the ply when the item was created. These item form pages are having the form.aspx page as the parent page under the 12/Templates/Pages folder. In this Forms.aspx page the web part zone is empty and the “ListformWebpart” is rendered dynamically when we create the item in the List. This relation between the form.aspx page and the ListformWebPart is mentioned in the schema.xml file of the List definition. Adding a task item is an example in this scenario.

·         So it’s not going to be possible to just replace the OOB people picker control with the custom people picker control.

·         The easiest way to render the custom people picker control in the item form pages is to ghost the pages through sharepoint designer and can create custom item form pages with the required control but the control will be available only in the site level not under the sharepoint farm level. It will increase the effort to customize the item form pages for the every site you create in the sharepoint farm.

 

      Finally to implement the custom people picker control across the sharepoint farm you need to implement the following steps

·         Create the custom field type and render the custom people picker control as the field rendering control for the custom field type.

·         Create a custom feature to register a “Site Column” of your custom field type created in the step a.

·         Create a custom feature to create a custom content type. Create the custom content type inheriting from any of the OOB content type,  for example if you want to replace the “Assigned To” field control of Task list with the custom people picker control then create the custom content type based on the OOB content type “Task”. Use the “RemoveFieldRef” attribute to remove the “Assigned To” field from the parent content type and add the new field reference of your custom field type (Site Column).

·         Now your custom content type is available with the custom Assigned To field which render the custom people picker control as the field is created based on the custom field type.

·         Again the code behind of the “Save Button” in the item form pages looks for the OOB Assigned To field and it will fail to locate one.

·         So you need to create the custom save button and need to replace the button through the sharepoint rendering template.

·         You need to create the custom Sharepoint Rendering template through customdefaulttemplates.ascx (By copying the “ListForm” rendering template from the defaulttemplates.ascx) control under the controltemplates folder. Need to replace the “SharePoint:SaveButton” with the custom save button in the custom rendering template.

·         The custom rendering template can be mentioned through the custom content type via the “XMLDocuments” tag.

·         Create the custom list definition and render the custom content type for the list definition

 

Custom Picker Control

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!!

Thanks to Eric Shupps
Before posting any blog item, I would like to thank my GURU "Eric Shupps" for allowing me to post on his web site