Skip to main content

Blog de Alejandro Avila

Go Search
Home
  

Blog de Alejandro Avila > Posts > How to Customize the User Information Page (Part 3)
How to Customize the User Information Page (Part 3)
 
UPDATED: Changed the Edit Button to override the default SP edit button to fix edit link bug. The sample solution has been updated to reflect the changes.
 
Continuing on from the User Information page customization series:
 
Part 1 talked about some of the difficulties presented with application pages in general.
Part 2 demonstrated how to redirect the user to a custom User Profile page using feature deployment.
This part will show how you can simply customize the look and feel of the User Profile page. Before reading this part you should read Part 2 and have a look at the sample code.
 
I am going to focus on the more significant changes - all the HTML/CSS changes including the custom master page have been left out (The code used is included in the sample solution though).
 
In order to reuse as much of what SharePoint provides as possible - I will base my customized User Profile page on the SharePoint userdisp.aspx page.
 
The first thing to do is to turn the userprofile.aspx page created in Part 2 into code behind page that extends the UserDisplayEditPageBase. To do this, create a class like so:
public class UserProfilePage : UserDisplayEditPageBase
 
To resolve the UserDisplayEditPageBase class you need a reference to Microsoft.SharePoint.ApplicationPages.dll which is not in the GAC. You will need to Browse to the location "C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\CONFIG\BIN" to find this dll.
I have included the dll in the sample source code for simplicity.
 
Now I will update my custom profile page to inherit from this  class:
<%@ Page Language="C#" Inherits="CustomUserProfile.UserProfilePage, CustomUserProfile, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1ba1bfabc83c4398" MasterPageFile="~/_layouts/application.master" %>
 
Note that that I have used the fully qualified name and this assumes that the dll will be signed and placed in the GAC. See the sample solution for how this can be easily done.
 
Now put the contents of the original userdisp.aspx (from the 12 Hive) into the userprofile.aspx page. The first modification to make is to remove the delegate control in the custom page or so you don't get stuck in an infinite redirect loop.
 
At this point I could just apply a custom master page and be done. This would let me easily apply a new look and feel, but I'd like to make a few modifcations to the layout as well.
 
You will probably have already noticed that the guts of the page are contained in a FormComponent control. This control provides a set of properties and methods that make it easy to display a form based on a SharePoint list item. It's rendering is controlled by the TemplateName property which is currently set to 'UserListForm'. We can find the contents of this form by looking in c:\program files\common files\microsoft shared\web server extensions\12\template\controltemplates\DefaultTemplates.ascx. I don't want to modify this file directly (it will affect all SharePoint sites) so I will take a copy of the SharePoint:RenderingTemplate and put it in a new ascx file named CustomTemplates.ascx (this will live in the controltemplates dir). I then give it a custom name so that it only overrides it for the profile display page. Now I should have a FormComponent in my profile page like:
<SharePoint:FormComponent id="UserListForm" TemplateName="CustomUserListForm" ControlMode="Display" runat="server"/>
and in CustomTemplates.ascx file I have:
<SharePoint:RenderingTemplate ID="CustomUserListForm" runat="server">
 
<Template>
   
<span id="part1">
      .....
 
Note that the TemplateName of the FormComponent matches up with the ID off the RenderingTemplate.
From here it is easy enough to edit some of the basic HTML elements of the form.
 
Next up is to customize the Toolbar. To do this copy the RenderingTemplate with the ID of "UserInfoListDisplayFormToolBar" from DefaultTemplates.ascx to the CustomTemplates.ascx file. I want to remove some of the buttons and have a custom Edit Item button so I can link to a custom user profile edit page. To do this change the control declaration from:
<SharePoint:UserInfoListFormToolBar runat="server"/>
to
<SharePoint:FormComponent id="UserToolBar" TemplateName="CustomUserInfoListDisplayFormToolBar" runat="server"/>
 
And then customize the RenderingTemplate like so:
<SharePoint:RenderingTemplate ID="CustomUserInfoListDisplayFormToolBar" runat="server">
<Template>
 
<script>
   
recycleBinEnabled = <SharePoint:ProjectProperty Property="RecycleBinEnabled" runat="server"/>;
 
</script>

 
<wssuc:ToolBar CssClass="ms-toolbar" id="toolBarTbl" runat="server" FocusOnToolbar="true">
   
<Template_Buttons>
     
<prof:UserProfileEditButton ID="UserProfileEditButton1" runat="server" />       <SharePoint:UserInfoListDeleteItemButton ID="UserInfoListDeleteItemButton1" runat="server"/>
   
</Template_Buttons>
 
</wssuc:ToolBar>
</Template>
</
SharePoint:RenderingTemplate>
 
Note that I have removed a few of the buttons for alerts and regional settings as well as create a custom button for linking to the useredit.aspx. 
The custom edit button simply overrides the standard SharePoint edit button and updates the URL:

public class UserProfileEditButton : UserInfoListEditItemButton
{
  protected override void OnLoad(EventArgs
e)
  {
    base
.OnLoad(e);
    base.NavigateUrl = base.NavigateUrl.Replace("useredit", "usermodify"
);
  }
}

Next I want to tidy up up the user display name as it includes the domain and won't have any meaning for most users.
To do this I override the OnPreRender method in the UserProfilePage class created earlier:
protected override void OnPreRender(EventArgs e)
{
 
base.LabelTitle.Text = base.UserListForm.ListItem.GetFormattedValue("Title"
);
}
This will give us a nicer looking display name:
 
 
 
In this case I don't want to display the SIP Address, so the next task is to remove this from the profile page. Currently all of the fields are rendered using a FieldIterator which is declared on the page as:
<SharePoint:ListFieldIterator runat="server"/>
 
In order to customize how the user list fields are displayed - we need to create a class that overrides the ListFieldIterator. My class is declared like this:
public class UserProfileFieldIterator : ListFieldIterator
 
Becuase I want to exclude the SIP Address I am then going to add override the IsFieldExcluded method like so:
protected override bool IsFieldExcluded(SPField field)
{
  if (field.Title == "SIP Address")
    return true;

  return base.IsFieldExcluded(field);
}

To replace the existing field Iterator currently being used I need to first register the assembly:
<%@ Register TagPrefix="prof" Namespace="CustomUserProfile" Assembly="CustomUserProfile, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1ba1bfabc83c4398" %>
 
and then replace the field iterator declaration with the custom one just made:
<prof:UserProfileFieldIterator ID="UserIterator" runat="server" />
 
The last thing I'm going to do is attach the custom master page. This is simply a case of changing userprofile.aspx to point to a new master page:

<%@ Page Language="C#" Inherits="CustomUserProfile.UserProfilePage, CustomUserProfile, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1ba1bfabc83c4398" MasterPageFile="~/_layouts/customprofile.master" %>

The custom master page also requires a couple of css files to override and add styles to the SharePoint page.
 
And now after all our hard work - "The final product":
 
 
You can download the sample code (including solution deployment) -> here.
 
Although I have only customized the SharePoint user info page you can do the same for the edit page - or any application page really.
 
I am considering doing a Part 4 with some advanced customizations such as having a custom action when closing the page (eg redirect) and modifying some of the form fields. Let me know if this is something that you are interested in.
 
For more information on Form Components, Rendering Templates and List Iterators have a look at the following resource:
 

Comments

There are no comments yet for this post.