Building a ‘Contacts’ web part
Ever wanted an easy way to pick people from your staff directory and display them on a page? Ever wanted to point this kind of web part at a AD security group and have it automatically display all the members? Then this web part is for you.
This is a on-premises web part, you’ll need Visual Studio and SharePoint installed to develop this. Start with a your project open and add a Visual Web Part . This doesn’t change between 2010 and 2019:
You will end up with the four standard files, note the extra CS file we’ll address that later:
So the ContactDetailsWebPart.cs looks like so:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Web.UI.WebControls.WebParts;
using YourNameSpaceWebParts.CONTROLTEMPLATES.YourNameSpace;
using Microsoft.SharePoint;
namespace YourNameSpaceWebParts.ContactDetailsWebPart
{
[ToolboxItem(false)]
public class ContactDetailsWebPart : WebPart, IWebEditable
{
// Visual Studio might automatically update this path when you change the Visual Web Part project item.
private const string _ascxPath = @"~/_CONTROLTEMPLATES/15/YourNameSpace/ContactDetailsWebPartUserControl.ascx";
public enum displayMode
{
BigPicture,
SmallPicture,
NoPicture
}
[WebBrowsable(true),
WebDisplayName("Display Mode"),
WebDescription(""),
Personalizable(
PersonalizationScope.Shared),
Category("Custom Properties"),
DefaultValue(displayMode.BigPicture)]
public displayMode DisplayMode
{
get;
set;
}
[Personalizable(PersonalizationScope.Shared)]
[WebBrowsable(false)]
public string Contacts { get; set; }
#region IWebEditable Members
EditorPartCollection IWebEditable.CreateEditorParts()
{
List<EditorPart> editors = new List<EditorPart> {new PeoplePickerEditor(ID)};
return new EditorPartCollection(editors);
}
object IWebEditable.WebBrowsableObject
{
get { return this; }
}
#endregion
protected override void CreateChildControls()
{
// Set username to current user adding Web Part by default
if (String.IsNullOrEmpty(Contacts))
{
string loginname = SPContext.Current.Web.CurrentUser.LoginName;
string[] loginnameArr = loginname.Split('\\');
Contacts = loginnameArr[1];
}
ContactDetailsWebPartUserControl control = Page.LoadControl(_ascxPath) as ContactDetailsWebPartUserControl;
if (control == null) return;
control.wp = this;
control.Username = Contacts;
Controls.Add(control);
}
}
}
Elements.xml defines the what/where of this web part:
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/" >
<Module Name="ContactDetailsWebPart" List="113" Url="_catalogs/wp">
<File Path="ContactDetailsWebPart\ContactDetailsWebPart.webpart" Url="YourNameSpace.WebParts_ContactDetailsWebPart.webpart" Type="GhostableInLibrary" ReplaceContent="TRUE" IgnoreIfAlreadyExists="FALSE">
<Property Name="Group" Value="The Intranet" />
</File>
</Module>
</Elements>
The web part file can be customised next, again the title and description are the parts your end users will see:
<?xml version="1.0" encoding="utf-8"?>
<webParts>
<webPart xmlns="http://schemas.microsoft.com/WebPart/v3">
<metaData>
<type name="YourNameSpace.WebParts.ContactDetailsWebPart.ContactDetailsWebPart, $SharePoint.Project.AssemblyFullName$" />
<importErrorMessage>$Resources:core,ImportErrorMessage;</importErrorMessage>
</metaData>
<data>
<properties>
<property name="Title" type="string">Contact Details WebPart</property>
<property name="Description" type="string">Display integrated contact details for a selection of users.</property>
</properties>
</data>
</webPart>
</webParts>
Now in Visual Studio add a new CS file, this will handle the custom logic required to handle the people picker control:
using Microsoft.SharePoint.WebControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
namespace YourNameSpace.WebParts.ContactDetailsWebPart
{
public sealed class PeoplePickerEditor : EditorPart
{
private PeopleEditor _peoplePicker;
public PeoplePickerEditor(string webPartID)
{
ID = "PeoplePickerEditor" + webPartID;
Title = "Select Contacts";
}
protected override void CreateChildControls()
{
_peoplePicker = new PeopleEditor
{
ID = "pe1",
AllowTypeIn = true,
AllowEmpty = false,
MultiSelect = true,
Width = Unit.Pixel(250),
SelectionSet =
PeopleEditor.AccountType.SecGroup.ToString() + "," + PeopleEditor.AccountType.SPGroup.ToString() +
"," + PeopleEditor.AccountType.User.ToString()
};
Controls.Add(_peoplePicker);
}
public override bool ApplyChanges()
{
EnsureChildControls();
ContactDetailsWebPart webPart = WebPartToEdit as ContactDetailsWebPart;
if (webPart != null)
{
webPart.Contacts = _peoplePicker.CommaSeparatedAccounts;
//PickerEntity entity
}
return true;
}
public override void SyncChanges()
{
EnsureChildControls();
ContactDetailsWebPart webPart = WebPartToEdit as ContactDetailsWebPart;
if (webPart != null)
{
_peoplePicker.CommaSeparatedAccounts = webPart.Contacts;
//_peoplePicker.ResolvedEntities = webPart.Contacts;
}
}
}
}
Now you should have a working web part if you compile and deploy your WSP package.
The title can be customised, the web part itself will show photos if you have them in your user profile service, it will show job title and phone number as well.
You can also control the picture via the web part properties. This for me seems like a nice way to automate an otherwise very manual admin task whenever a teams membership changes.
If you have role based groups setup that means your security groups for teams are automatically updated, then hooking them into this web part means your teams contact information will always be up to date!