In the previous article about People Picker functionality I described the PeopleEditor control. The Browse button of the PeopleEditor initiates the search dialog containing the Picker.aspx page described below.
Picker.aspx
Picker.aspx is a page used for many built-in entity pickers and, along with its master-page pickerdialog.master, located at 14\TEMPLATE\LAYOUTS. Both the page and master-page contain a lot of PlaceHolders that are stuffed with different controls and contents depending on the type of the picker we use. In case of the People Picker the most noteworthy PlaceHolders defined in the Picker.aspx are
- PlaceHolderDialogControl;
- PlaceHolderQueryControl;
- PlaceHolderHtmlMessage;
- PlaceHolderError;
- PlaceHolderResultControl;
- PlaceHolderEditorControl.
Take a look at a simplified markup below to figure out where these PlaceHolders are situated within the Picker.aspx (the Html comments, indents and formatting are added for clarity):
...
<asp:Content contentplaceholderid="PlaceHolderDialogBodySection"
runat="server">
...
<!-- PlaceHolderDialogControl -->
<asp:PlaceHolder runat="server" id="PlaceHolderDialogControl"/>
<table class="ms-pickerbodysection" cellspacing="0" cellpadding="0"
width='100%' height='100%'>
...
<tr>
<td width='15px'> </td>
<td width='100%' height="20px">
<!-- PlaceHolderQueryControl -->
<asp:PlaceHolder runat="server" id="PlaceHolderQueryControl"/>
</td>
<td width='15px'> </td>
</tr>
<tr>
<td width='15px'>
<img src="/_layouts/images/blank.gif" width='15' height='1' alt="" />
</td>
<td class="ms-descriptiontext">
<!-- PlaceHolderHtmlMessage -->
<asp:PlaceHolder runat="server" id="PlaceHolderHtmlMessage"/>
</td>
<td width='15px'>
<img src="/_layouts/images/blank.gif" width='15' height='1' alt="" />
</td>
</tr>
<tr>
<td width='15px'> </td>
<td class="ms-descriptiontext" style="color:red;">
<!-- PlaceHolderError -->
<asp:PlaceHolder runat="server" id="PlaceHolderError"/>
</td>
<td width='15px'> </td>
</tr>
<tr height='100%'>
<td width='15px'>
<img src="/_layouts/images/blank.gif" width='15' height='200' alt="" />
</td>
<td>
<table cellspacing="0" cellpadding="0" width='100%' height='100%'
class="ms-pickerresultoutertable">
<tr height="100%">
...
<td id="ResultArea">
<div id='resultcontent' class="ms-pickerresultdiv">
<!-- PlaceHolderResultControl -->
<asp:PlaceHolder runat="server" id="PlaceHolderResultControl"/>
</div>
</td>
</tr>
</table>
</td>
<td width='15px'>
<img src="/_layouts/images/blank.gif" width='15' height='200' alt="" />
</td>
</tr>
...
<tr id="EditorRow" runat="server">
<td width='15px'> </td>
<td width="100%">
<table width="100%" cellspacing="0" cellpadding="0">
<tr>
<td>
<input type='button' id='AddSel' runat='server' disabled
class='ms-NarrowButtonHeightWidth' onclick='addSelected_Click();'
accesskey="<%$Resources:wss,picker_AddSelAccessKey%>" />
</td>
<td width="10px">
<img src="/_layouts/images/blank.gif" width='4' height='1' alt="" />
</td>
<td width='100%'>
<!-- PlaceHolderEditorControl -->
<asp:PlaceHolder runat="server" id="PlaceHolderEditorControl"/>
</td>
</tr>
</table>
</td>
<td width='15px'> </td>
</tr>
...
</table>
...
</asp:Content>
Clicking the Browse button of PeopleEditor requests the Picker.aspx with a number of query string parameters. Below is an example of such url after url decoding (indents and formatting are added for clarity):
http://servername/mysitecollection/_layouts/Picker.aspx?
MultiSelect=True&
CustomProperty=User,SecGroup,DL;;15;;;False&
DialogTitle=Select People and Groups&
DialogImage=/_layouts/images/ppeople.gif&
PickerDialogType=Microsoft.SharePoint.WebControls.PeoplePickerDialog,
Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral,
PublicKeyToken=71e9bce111e9429c&
ForceClaims=False&
DisableClaims=False&
EnabledClaimProviders=&
EntitySeparator=;;??????&
DefaultSearch=
Among search and dialog options there is such parameter as PickerDialogType containing a fully qualified type name, in this case it’s PeoplePickerDialog. Having read this parameter the Picker.aspx creates an instance of PeoplePickerDialog through the Reflection. Below is the shortened code doing that, this code is taken from the OnLoad method of the Picker.aspx:
...
// get the type
Type type = Utility.GetTypeFromAssembly(Request["PickerDialogType"], true, false);
...
// create instance through Reflection
this.DialogControl = (PickerDialog) Activator.CreateInstance(type);
...
// set some search options based on query string parameters
this.DialogControl.CustomProperty = Request["CustomProperty"];
...
string str3 = Request["MultiSelect"];
if (str3 != null)
this.DialogControl.MultiSelect = bool.Parse(str3);
PeoplePickerDialog
PeoplePickerDialog, a control the main goal of which is to supply with other visual controls to be put into PlaceHolders of the Picker.aspx. So, the PeoplePickerDialog creates some controls and exposes references to them as properties, but doesn’t add them to its inner Controls-collection and, therefore, doesn’t render them on its own. Let’s see what controls are created by PeoplePickerDialog. Below are constructors of the PeoplePickerDialog and its base class, PickerDialog, respectively:
// the constructor of PeoplePickerDialog
public PeoplePickerDialog() : base(new PeopleQueryControl(),
new HierarchyResultControl(),
new PeopleEditor(), true)
{
...
}
// the main constructor of the base class, PickerDialog
public PickerDialog(PickerQueryControlBase query, PickerResultControlBase result,
EntityEditorWithPicker editor)
{
...
this.ErrorMessageLabel = new Label();
// the ErrorMessageLabel field is available through the ErrorLabel property
this.m_HtmlMessageLabel = new Label();
// the m_HtmlMessageLabel field is available through the HtmlMessageLabel property
this.QueryControlValue = query;
// the QueryControlValue field is available through the QueryControl property
this.ResultControlValue = result;
// the ResultControlValue field is available through the ResultControl property
this.EditorControlValue = editor;
// the EditorControlValue field is available through the EditorControl property
...
}
As we can see, when the Picker.aspx instantiates the object of PeoplePickerDialog through the Reflection a number of visual controls are created. How does the Picker.aspx use them? Below is the code taken again from the OnLoad method of the Picker.aspx:
...
// add the PeoplePickerDialog itself to the PlaceHolderDialogControl of the picker.aspx.
this.PlaceHolderDialogControl.Controls.Add(this.DialogControl);
// add controls supplied by the PeoplePickerDialog to some PlaceHolders of the picker.aspx
this.PlaceHolderEditorControl.Controls.Add(this.DialogControl.EditorControl);
this.PlaceHolderResultControl.Controls.Add(this.DialogControl.ResultControl);
this.PlaceHolderQueryControl.Controls.Add(this.DialogControl.QueryControl);
...
// add controls supplied by the PeoplePickerDialog to some PlaceHolders of the picker.aspx
this.PlaceHolderError.Controls.Add(this.DialogControl.ErrorLabel);
this.PlaceHolderHtmlMessage.Controls.Add(this.DialogControl.HtmlMessageLabel);
The picture below demonstrates where the basic controls are located within the dialog:
Note the HtmlMessageLabel and ErrorLabel are not presented in the picture, but they reside in the appropriate PlaceHolders between PeopleQueryControl and HierarchyResultControl.
As we remember the PeopleEditor opens the search dialog. Interestingly that the dialog uses the same PeopleEditor control to hold selected users and groups. Note, however, the PeopleEditor within the dialog hides its buttons (Check Names and Browse) and doesn’t allow typing anything.
Besides creating and exposing the controls the PeoplePickerDialog also provides with some JavaScripts, exposes search parameters, defines some elements of the dialog’s appearance (title, for example), defines columns to be displayed in the table of search results and so on.
Related posts: