MOSS2007中创建栏默认有很多类型,如单选文本、多选文本、选项、数字、日期和时间等。这些栏本身也存在一些问题,如单行文本不能超过255个字符等。
当MOSS提供的栏不能够满足具体要求的时候,就需要自定义一个栏类型,如图8-12所示。
图8-12 默认的栏类型
在WSS 3.0中,添加了一个可扩展字段类型,可以通过C#或者Visual Basic来编写可扩展字段,所有的可扩展字段继承自如SPFieldText、SPFieldMultiLineText、SPFieldDateTime这样的内置SharePoint类型。
下表列举了MOSS中栏的类型及其字段类型说明
表8-5 常用的字段类型
名 称 | 字段类型 |
单行文本 | SPFieldText |
多行文本 | SPFieldMultilineText |
选项 | SPFieldChoice |
数字 | SPFieldNumber |
货币 | SPFieldCurrency |
日期 | SPFieldDateTime |
是/否 | SPFieldBoolean |
用户或用户组 | SPFieldUser |
超链接或图片 | SPFieldUrl |
查阅项 | SPFieldLookup |
8.4.1 字段类型构成
一个自定义字段类型由下面几个部分组成。
Ø 字段类型
Ø 字段值类(这个不是必需的)
Ø 字段展现部分(可以是用户控件,或者直接输出)
Ø 字段描述文件(必须是以fldtypes_开头的文件)
8.4.2 自定义字段类型的部署
如果有字段界面(用户控件),需要将其复制到C:/Program Files/Common Files/ Microsoft Shared/web server extensions/12/TEMPLATE/CONTROLTEMPLATES这个目录下。
把字段描述文件复制到C:/Program Files/Common Files/Microsoft Shared/web server extensions/12/TEMPLATE/XML这个目录下。
注册程序集到GAC并重新启动IIS。
8.4.3 代码示范
这段代码构造了一个下拉列表,列表中能够直接显示层次分类。
打开VS2005,新建SharePoint类型的“Empty”工程,命名为ITSM.CustomFields,单击“确定”按钮。如图8-13所示。
图8-13 新建一个SharePoint的空白工程
右键单击解决方案资源管理器属性面板中的ITSM.CustomFields项目属性,添加→新建项,选择Field Control类型,命名为ddlTree,如图8-14所示。
图8-14 添加一个Field Control类型的项目
最终工程文件如图8-15所示。
图8-15 生成后的项目文件列表
双击ddlTree.Field.cs,这就是字段类型的类文件。
需要说明的是这个类从SPFieldChoice选项控件中继承。其余的代码都是系统用模板自动生成的。代码如下所示:
using System;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.Security;
namespace ITSM.CustomFields
{
[CLSCompliant(false)]
[Guid("9e7e323b-8198-4132-85c8-7701508a13e0")]
public class ddlTreeField :SPFieldChoice
{
public ddlTreeField(SPFieldCollection fields, string fieldName)
: base(fields, fieldName)
{
}
public ddlTreeField(SPFieldCollection fields, string typeName, string displayName)
: base(fields, typeName, displayName)
{
}
public override BaseFieldControl FieldRenderingControl
{
[SharePointPermission(SecurityAction.LinkDemand, ObjectModel = true)]
get
{
BaseFieldControl fieldControl = new ddlTreeFieldControl();
fieldControl.FieldName = this.InternalName;
return fieldControl;
}
}
}
}
双击打开ddlTree.FieldControl.cs文件,这个类从BaseFieldControl继承。
using System;
using System.Runtime.InteropServices;
using System.Data;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.Security;
using System.Web.UI.WebControls;
namespace ITSM.CustomFields
{
[CLSCompliant(false)]
[Guid("bb198aa7-1063-4b09-b05e-ecdbfcdaae5a")]
public class ddlTreeFieldControl : BaseFieldControl
{
protected DropDownList ddlTree;
protected override string DefaultTemplateName
{
get { return " ddlTreeFieldRendering"; }
}
public override object Value
{
get
{
EnsureChildControls();
return ddlTree.SelectedValue;
}
set
{
EnsureChildControls();
ddlTree.SelectedValue = (string)this.ItemFieldValue;
}
}
public override void Focus()
{
EnsureChildControls();
ddlTree.Focus();
}
protected override void CreateChildControls()
{
if (Field == null)
return;
base.CreateChildControls();
if (ControlMode == SPControlMode.Display)
return;
ddlTree = (DropDownList)TemplateContainer.FindControl ("ddlTree");
if (ddlTree == null)
throw new ArgumentException("未发现ddlTree控件");
ddlTree.ToolTip = Field.Title + "ddlTree";
ddlTree.TabIndex = this.TabIndex;
ddlTree.CssClass = this.CssClass;
if (!Page.IsPostBack)
{
//这里读取数据,帮定下拉列表
BindData();
}
}
string sourceTreeList = "tree";
private void BindData()
{
SPWeb web = SPControl.GetContextWeb(Context);
SPList treeList = web.Lists[sourceTreeList];
SPListItemCollection caseItems = treeList.Items;
//添加父分类
this.ddlTree.Items.Add(new ListItem("设置为一级分类", "0"));
//一次性返回
DataTable dt = caseItems.GetDataTable();
if (dt.Rows.Count > 0)
{
foreach (DataRow dr in dt.Rows)
{
if (dr["ParentID"].ToString().Trim() == "0")
{
ddlTree.Items.Add(new ListItem(dr["ClassName"]. ToString(), dr["ClassID"].ToString()));
this.BindChildData(dt, dr["ClassID"].ToString(), 1);
}
}
}
}
private void BindChildData(DataTable dt, string ClassID, int n)
{
//在DataTable中过滤,而不是再次读取数据库
DataRow[] rows = dt.Select("ParentID=" + ClassID + "", "ClassID");
for (int i = 0; i < rows.Length; i++)
{
ddlTree.Items.Add(new ListItem(this.SpaceLength(n) + rows[i]["ClassName"].ToString(), rows[i]["ClassID"].ToString()));
this.BindChildData(dt, rows[i]["ClassID"].ToString(), n + 1);
}
}
private string SpaceLength(int i)
{
string space = "";
for (int j = 0; j < i; j++)
{
space += " ";
}
return space + "└";
}
}
}
手工添加一个用户控件文件ddlTreeFieldRendering.ascx,代码如下所示:
<%@ 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="ddlTreeFieldRendering" runat="server">
<Template>
<asp:DropDownList runat="server" ID="ddlTree"></asp:DropDownList>
</Template>
</SharePoint:RenderingTemplate>
需要注意的是,用户控件的名称和RenderingTemplate控件的ID需要保持一致。并且与ddlTreeValue.FieldControl.cs 这个文件中的DefaultTemplateName属性值一致。
8.4.4 部署
定义字段描述文件必须以fldtypes_开头,这样MOSS才能认为这是一个字段定义文件,创建一个字段描述文件,命名为fldtypes_ddlTree.xml。
解释一下这个文件的节点
TypeName:栏的类型名称。
ParentType:栏的类型,这里是Choice。也就是选项类型
TypeDisplayName:栏的类型说明,如图8-16所示。
图8-16 TypeDisplayName显示情况
TypeShortDescription:显示在栏内的信息类型说明,如图8-17所示。
图8-17 TypeShortDescription显示情况
FieldTypeClass:分为两节,第一节为命名空间+类名,第二节是生成程序集的名称,可以通过Reflector工具获得,如图8-18所示。
图8-18 字段描述文件的说明
<FieldTypes>
<FieldType>
<Field Name="TypeName">下拉列表</Field>
<Field Name="ParentType">Choice</Field>
<Field Name="TypeDisplayName">这是一个下拉列表</Field>
<Field Name="TypeShortDescription">直接多级的下拉列表</Field>
<Field Name="UserCreatable">TRUE</Field>
<Field Name="ShowOnListAuthoringPages">TRUE</Field>
<Field Name="ShowOnDocumentLibraryAuthoringPages">TRUE</Field>
<Field Name="ShowOnSurveyAuthoringPages">TRUE</Field>
<Field Name="ShowOnColumnTemplateAuthoringPages">TRUE</Field>
<Field Name="FieldTypeClass">
ITSM.CustomFields.ddlTreeField,
ITSM.CustomFields, Version=1.0.0.0,Culture=neutral, PublicKeyToken=9f4da00116c38ec5
</Field>
<RenderPattern Name="DisplayPattern">
<Switch>
<Expr>
<Column/>
</Expr>
<Case Value="">
</Case>
<Default>
<Column SubColumnNumber="0" HTMLEncode="TRUE"/>
<HTML><![CDATA[<BR>]]></HTML>
<Column SubColumnNumber="1" HTMLEncode="TRUE"/>
<HTML><![CDATA[ - ]]></HTML>
<Column SubColumnNumber="2" HTMLEncode="TRUE"/>
<HTML><![CDATA[<BR>]]></HTML>
<Column SubColumnNumber="3" HTMLEncode="TRUE"/>
</Default>
</Switch>
</RenderPattern>
</FieldType>
</FieldTypes>
把ddlTreeFieldRendering.ascx复制到C:/Program Files/Common Files/Microsoft Shared/web server extensions/12/TEMPLATE/CONTROLTEMPLATES这个目录下。
把fldtypes_ddlTree.xml复制到C:/Program Files/Common Files/Microsoft Shared/web server extensions/12/TEMPLATE/XML这个目录下。
注册程序集到GAC并重新启动IIS。
提供一个批处理文件Install.bat,批处理文件的功能是复制文件并注册程序集到GAC并新重启动IIS。
echo Copying the feature...
echo.
copy /Y ddlTreeFieldRendering.ascx "%CommonProgramFiles%/Microsoft Shared/web server extensions/12/TEMPLATE/CONTROLTEMPLATES/"
copy /Y fldtypes_ddlTree.xml "%CommonProgramFiles%/Microsoft Shared/web server extensions/12/TEMPLATE/XML/"
echo.
echo Adding assemblies to the GAC...
echo.
"D:/Program Files/Microsoft Visual Studio 8/SDK/v2.0/Bin/gacutil.exe" -uf ITSM.CustomFields
"D:/Program Files/Microsoft Visual Studio 8/SDK/v2.0/Bin/gacutil.exe" -if bin/Debug/ITSM.CustomFields.dll
echo Doing an iisreset...
echo.
popd
iisreset
打开一个知识库列表,选择创建栏,可以看到如图8-19所示的界面。
图8-19 创建栏时的可以看到创建的新栏类型
选择“直接多级的下拉列表”,并创建一个栏,命名为“分类”点击单击“确定”按钮即可。在知识库列表的工具条上,点击单击“新建”链接,打开如图8-20所示的界面。
图8-20 添加自定义栏的最终界面