Sharepoint Custom Control Creating custom Multi Choice field type
Create a new C# Class Library project in Visual Studio .NET. After created, add a reference toMicrosoft.SharePoint.dll and System.Web.dll. Sign your project with a new key to make your assembly strong named. PublicColumnValue.cs Add a class called PublishColumnValue and let it inherit from SPFieldMultiChoiceValue. Create two constructors: **************************************************************************** using System; using System.Collections.Generic; using System.Text; using Microsoft.SharePoint; using System.Web.UI; using Microsoft.SharePoint.WebControls;
namespace Etter.Column {
public class PublishColumnValue : SPFieldMultiChoiceValue {
public PublishColumnValue() : base() { }
public PublishColumnValue( string value ) : base( value ) { } } } *************************************************************** PublicColumn.cs Add a class called PublishColumn and let it inherit from SPFieldMultiChoice. Create two constructors: *************************************************************** using System; using System.Collections.Generic; using System.Text; using Microsoft.SharePoint; using Microsoft.SharePoint.WebControls;
namespace Etter.Column { public class PublishColumn : SPFieldMultiChoice {
public PublishColumn( SPFieldCollection fields, string fieldName ) : base( fields, fieldName ) { }
public PublishColumn( SPFieldCollection fields, string typeName, string displayName ) : base( fields, typeName, displayName ) { } } } Override the GetFieldValue property, which will return the new PublicColumnValue type: public override object GetFieldValue( string value ) { if( string.IsNullOrEmpty( value ) ) { return null; } return new PublishColumnValue( value ); } ***************************************************************** The last thing you have to do in this class is overriding the FieldRenderingControl property. This property tells SharePoint which control to use to render the field: public override BaseFieldControl FieldRenderingControl { get { BaseFieldControl control = new PublishColumnControl(); control.FieldName = InternalName; return control; } } ****************************************************************** PublishColumnControl.ascx Now this is a C# Class Library project, so you need to add an ascx-file not by clicking Add > New Item, but by copying an ascx-file from some other project and replace the content by: <%@ Control Language="C#" Debug="true" %> <%@Assembly Name="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> <%@Register TagPrefix="SharePoint" Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" namespace="Microsoft.SharePoint.WebControls"%>
<SharePoint:RenderingTemplate ID="PublishColumnRendering" runat="server"> <Template> <asp:CheckBoxList ID="cblLocations" runat="server" /> </Template> </SharePoint:RenderingTemplate> PublishColumnControl.cs Add a new class called PublishColumnControl and make it inherit from BaseFieldControl. Also declare the checkbox we are going to use: using System; using System.Collections.Generic; using System.Text; using Microsoft.SharePoint.WebControls; using System.Web.UI.WebControls;
namespace Etter.Column { protected CheckBoxList cblLocations; public class PublishColumnControl : BaseFieldControl { } } ************************************************************* To tell SharePoint which rendering template to use, override the DefaultTemplateName property and return the ID of the RenderingTemplate in PublishColumnControl.ascx: protected override string DefaultTemplateName { get { return "PublishColumnRendering"; } }
Override the CreateChildControls method so we can get a reference to the cblLocations checkboxlist and change some properties: protected override void CreateChildControls() { if( Field == null ) { return; } base.CreateChildControls();
if( ControlMode == SPControlMode.Display ) { return; }
cblLocations = TemplateContainer.FindControl( "cblLocations" ) as CheckBoxList; if( cblLocations == null ) { throw new ArgumentException( "cblLoations could not be found" ); }
cblLocations.TabIndex = TabIndex; cblLocations.CssClass = CssClass; cblLocations.Items.Add( new ListItem( "item 1" ) ); cblLocations.Items.Add( new ListItem( "item 3" ) ); cblLocations.Items.Add( new ListItem( "item 2" ) ); } First we check if the Field is not null and if the control is not in display mode (we define the rendering of the display mode in the fldtypes_PublishColumn.xml file). After that we try to get a reference to the checkboxlist, set some properties and add list items. Last but not least we are going to override the Value property which sets and gets the value of the field type as a PublishColumnValue object: public override object Value { get { EnsureChildControls(); PublishColumnValue fieldValue = new PublishColumnValue(); foreach( ListItem item in cblLocations.Items ) { if( item.Selected ) { fieldValue.Add( item.Value ); } } return fieldValue; } set { EnsureChildControls(); cblLocations.ClearSelection();
PublishColumnValue fieldValue = (PublishColumnValue)value; for( int i = 0; i < fieldValue.Count; i++ ) { string s = fieldValue[i]; if( cblLocations.Items.FindByValue( s ) != null ) { cblLocations.Items.FindByValue( s ).Selected = true; } } } } ************************************************************* Fldtypes_PublishColumn.xml Add a xml file fldtypes_PublishColumn.xml. This xml file will hold the field type definition which SharePoint needs for every field. <?xmlversion="1.0"encoding="utf-8" ?> <FieldTypes> <FieldType> <FieldName="TypeName">PublishColumn</Field> <FieldName="ParentType">MultiChoice</Field> <FieldName="TypeDisplayName">Publish</Field> <FieldName="TypeShortDescription">Publish location</Field> <FieldName="UserCreatable">TRUE</Field> <FieldName="ShowOnListAuthoringPages">TRUE</Field> <FieldName="ShowOnDocumentLibraryAuthoringPages">TRUE</Field> <FieldName="ShowOnSurveyAuthoringPages">TRUE</Field> <FieldName="ShowOnColumnTemplateAuthoringPages">TRUE</Field> <FieldName="FieldTypeClass">Etter.Column.PublishColumn, Etter.Column, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b7331c42d890b827</Field> <PropertySchema> <Fields> </Fields> </PropertySchema> <RenderPatternName="DisplayPattern"> <ColumnHTMLEncode="TRUE"/> </RenderPattern> </FieldType> </FieldTypes> The FieldTypeClass has the following format: <namespace and class>,<full strong name assembly>. RenderPattern holds de definition that will be used to render the field in display mode. Deploying to SharePoint Of course it would be the best if you add this field type to a feature and deploy it with a solution package, but for now I will explain how to deploy it by hand: • Build your C# class library project and deploy the assembly to the GAC. • Copy the PublishColumnControl.ascx file to the c:\program files\Common files\microsoft shared\web server extensions\12\TEMPLATE\CONTROLTEMPLATES\ folder. • Copy the fldtypes_PublishColumn.xml file to the c:\program files\Common files\microsoft shared\web server extensions\12\TEMPLATE\XML\ folder. • IISRESET. Open a list on your SharePoint portal and add a new column based on the PublishColumn you created. |