Well in this case possibly not a gem and maybe not so hidden but at the very least a shiny rock under a bit of sand. Have you ever been developing a custom form page in SharePoint and you wanted to mimic the look & feel of other SharePoint forms? It's not terribly difficult with a few well placed controls and some reuse of existing CSS styles but there is an easier way, but before I getting started let me show you what I'm referring to:
Note the grouping, the descriptions of the grouping,the labeling of the input fields, and other things you don't see in this image including the validation and example text.
In this solution we'll be working within a couple out of the box user controls called the InputFormSection and the InputFormControl. The user controls can be found in the 12 hive located at C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\TEMPLATE\CONTROLTEMPLATES InputFormSection.ascx and InputFormControl.ascx respectively. Additionally we have available in our arsenal a host of controls inherited from the standard asp.net controls such as the validator controls (InputFormRequiredFieldValidator) and input controls (InputFormTextBox and InputFormCheckBox ) many of them with additional functionality such as richtexteditor functionality.
For our purposes we'll be developing a new FBA registration page. To start with we'll need to register some tag prefixes.Notice that the SharepointUserControl prefixes for InputFormsection and InputFormControl are both user controls found in the control templates folder referenced above. The SharepointControl prefix refers to an assembly with standard server controls. (Note: I usually prefer to define these prefixes in the controls section of the web.config so I don't have to define them at the top of every page.)
<%@ Register TagPrefix="SharepointUserControl" TagName="LinksTable" src="/_controltemplates/LinksTable.ascx" %> <%@ Register TagPrefix="SharepointUserControl" TagName="InputFormSection" src="/_controltemplates/InputFormSection.ascx" %> <%@ Register TagPrefix="SharepointUserControl" TagName="InputFormControl" src="/_controltemplates/InputFormControl.ascx" %> <%@ Register Tagprefix="SharepointControl" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint,
Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
Next is the meat of the implementation. We've created a two section form for user registration:
<asp:Content ID="Content15" ContentPlaceHolderId="PlaceHolderMain" runat="server"> <TABLE class="ms-propertysheet" border="0" width="100%" cellspacing="0" cellpadding="0"> <SharepointUserControl:InputFormSection runat="server" Title="Accound Details"
Description="Please provide a username, password, and email for your account."> <template_inputformcontrols> <SharepointUserControl:InputFormControl runat="server" ID="txtUserNameField" LabelText="User Name:" ExampleText="jdoe" > <Template_Control> <SharepointControl:InputFormTextBox Title="Username" class="ms-input" ID="txtUserName" ErrorMessage="Required"
Runat="server" TextMode="SingleLine" Columns="40" Rows="5"/> <SharepointControl:InputFormRequiredFieldValidator ID="valUserName" runat="server" Display="Dynamic"
ControlToValidate="txtUserName" BreakBefore="true"></SharepointControl:InputFormRequiredFieldValidator> </Template_Control> </SharepointUserControl:InputFormControl> <SharepointUserControl:InputFormControl runat="server" ID="txtPassword" LabelText="Password:" > <Template_Control> <SharepointControl:InputFormTextBox Title="Password" class="ms-input" TextMode="Password" ID="InputFormTextBox1"
Runat="server" Columns="40"/> </Template_Control> </SharepointUserControl:InputFormControl> <SharepointUserControl:InputFormControl runat="server" ID="txtConfirmPassword" LabelText="Confirm Password:"> <Template_Control> <SharepointControl:InputFormTextBox Title="Confirm Password" TextMode="Password" class="ms-input" ID="InputFormTextBox2"
Runat="server" Columns="40"/> </Template_Control> </SharepointUserControl:InputFormControl> <SharepointUserControl:InputFormControl runat="server" ID="txtEmail" LabelText="Email:" ExampleText="jdoe@example.com"> <Template_Control> <SharepointControl:InputFormTextBox Title="Email" class="ms-input" ID="txtEmailInpute" Runat="server"
TextMode="SingleLine" Columns="40"/> </Template_Control> </SharepointUserControl:InputFormControl> </template_inputformcontrols> </SharepointUserControl:InputFormSection> <SharepointUserControl:InputFormSection id="frmSectionUserInformation" runat="server" Title="Account Profile"
Description="Plase provide some basic information to help us personalize your experience on our site."> <template_inputformcontrols> <SharepointUserControl:InputFormControl runat="server" ID="txtFirstNameField" LabelText="First Name:" ExampleText="John" > <Template_Control> <SharepointControl:InputFormTextBox Title="First Name" class="ms-input" ID="txtFirstName" Runat="server"
TextMode="SingleLine" Columns="40"/> <SharepointControl:InputFormRequiredFieldValidator ID="valFirstName" runat="server" Display="Dynamic"
ControlToValidate="txtFirstName" BreakBefore="true"></SharepointControl:InputFormRequiredFieldValidator> </Template_Control> </SharepointUserControl:InputFormControl> <SharepointUserControl:InputFormControl runat="server" ID="txtLastNameField" LabelText="Last Name:" ExampleText="Doe" > <Template_Control> <SharepointControl:InputFormTextBox Title="Last Name" class="ms-input" ID="txtLastName" Runat="server"
TextMode="SingleLine" Columns="40"/> <SharepointControl:InputFormRequiredFieldValidator ID="valLastName" runat="server" Display="Dynamic"
ControlToValidate="txtLastName" BreakBefore="true"></SharepointControl:InputFormRequiredFieldValidator> </Template_Control> </SharepointUserControl:InputFormControl> <SharepointUserControl:InputFormControl runat="server" ID="txtSignatureField" LabelText="Signature:" > <Template_Control> <SharepointControl:InputFormTextBox Title="Signature" class="ms-input" ID="txtSignature"
Runat="server" TextMode="MultiLine" Rows="5" RichTextMode="FullHtml" RichText="true" Columns="40"/> </Template_Control> </SharepointUserControl:InputFormControl> </template_inputformcontrols> </SharepointUserControl:InputFormSection> </TABLE> <asp:Button runat="server" id="btnRegister" Text="Register" CssClass="ms-ButtonHeightWidth" OnClick="btnRegister_Click" /> </asp:Content>
Finally we are left with a UI with the comment look & feel:
A pretty good end result with minimal custom work although there are a couple annoyances. The first being the fact that the InputFormSection must be within a developer created table tag (they render as rows). IMO this is a poor implementation as the control should not put this kind of dependency out there even if it meant creating a parent control of something like InputForm that took care of those details. Related to that we also have the typical MS dependency of table based layouts. This should be nothing new to sharepoint (and asp.net) developers but it something that has always been a pet peeve of mine. I understand the need for backwards compatibility with old browsers but that can still be achieved with CSS and you are still be able to receive the benefits of CSS based layouts. Could it be that they are a bit afraid to jump in to the world of the average developer that uses CSS these days ;) , there can't be that many shops still running IE3 lol.
There are additional controls in that namespace but not too many with good documentation other then basic generated namespace and method information. In this case reflector is your friend to discover what they can do. If anyone would like to see more examples of some of the other controls let me know. I've used most of them at one time or another. But there it is, enjoy.