SharePoint中的列表(List) 与Content Type 之五

定义自定义的field types

====================

在前面的部分, 你看到了使用WSS内建的field type(Text, Choice, 和Notes)来创建自定义的site column definitions 的例子. WSS 3.0还引入了在一个更低的层次上工作的能力, 你可以定义你自己自定义的custom field type. 这样做的动机是获得对column之底层的初始化, 渲染, 和数据合法性验证的更高水平的控制.

 

比如说, 你需要为一个custom list创建一个column, 这个column展现一个user, 还带有一个drop-down list, 里面的数据时从一个后台数据库或者web service中获得的. 另一个场景是, 你需要一个column, 其中的数值被限制为必须满足domain-specific的合法性验证逻辑, 这个逻辑是你用托管代码(C# 或Visual Basic .NET)编写的. 在这些场景下, 创建一个custom field type是合情合理的.

 

custom field type 代表着一个column的新的数据类型. Custom field types 对于.net 的developer是有吸引力的, 因为他们使用托管代码编写的, 可以被编译为程序集然后部署到GAC中. 除了让托管代码执行初始化, 合法性验证以外, custom field type 还在一个或多个ASP.NET server-side controls 里有定义, 这给了你控制渲染的能力, 还使得你可以使用标准ASP.NET 开发中的流行技术.

 

为了创建一个custom field type, 你应该在Visual Studio中创建一个新的class library工程. 这一章的实例代码已经包含了一个例子工程, 名字叫做LitwareFieldTypes , 其中提供了所有用于实现和部署两个custom field types所需的代码. 注意, LitwareFieldTypes 工程被配置为编译到它自己的output之下, 带有一个强命名, 所以呢它可以被部署到GAC中. 部署到GAC中是部署和测试custom field type所需要的.

 

在源文件中, 包含着一个叫做LitwareFieldTypes.cs的代码文件, 其中有两个托管的类用来定义名为CompanySize的custom field type. 第一个类名字叫做CompanySizeField , 被用来定义custom field type 本身. 这个类继承自SPFieldText 类, SPFieldText 是定义在核心的WSS程序集Microsoft.SharePoint.dll中的. 第二个类名为CompanySizeFieldControl. 这个类是用来创建和初始化一个ASP.NET的DropDownList 控件的, 这个控件会给我们custom field type 一个自定义的渲染行为. 注意CompanySizeFieldControl 类继承自Microsoft.SharePoint.dll 中的一个名为BaseFieldControl的类.

 

提示:

完整的custom field type base classes(custom field type基类), 可以参考SDK中的“Custom Field Type Classes”主题. 所有的Field Type名字都是由SPField开始的, 包括Boolean, choice, currency, date, text, URL, 和multiple column fields.

 

下面的代码属于CompanySizeField类. 这个类提供了所有custom field types都会使用的两个标准的构造函数. 还有一个公共的只读属性, 叫做FieldRenderingControl , 它是用来创建CompanySizeFieldControl 类的实例的. 最后, 有一个方法名为GetValidatedString的重写了的方法. 你重写这个方法来添加你自己的自定义合法性验证逻辑. 在我们的例子中, 我们简单地验证了一下这个代码是不是empty的. 然而, 你应该添加额外的验证逻辑, 来满足你复杂商业应用的需要.

 

The CompanySizeField Class

public class CompanySizeField : SPFieldText
{
    // each field type requires two standard constructors
    public CompanySizeField(SPFieldCollection fields, string fieldName)
        : base(fields, fieldName) { }
    public CompanySizeField(SPFieldCollection fields, string typeName,
                            string displayName)
        : base(fields, typeName, displayName) { }
    // public property used to instantiate control used for rendering
    public override BaseFieldControl FieldRenderingControl
    {
        get
        {
            BaseFieldControl control = new CompanySizeFieldControl();
            control.FieldName = this.InternalName;
            return control;
        }
    }
    // Standard method override used to add validation logic
    public override string GetValidatedString(object value)
    {
        if (this.Required || value.ToString().Equals(string.Empty))
        {
            throw new SPFieldValidationException("Company size not assigned");
        }
        return base.GetValidatedString(value);
    }
}

 

下一步, 我们来看看CompanySizeFieldControl 是如何被书写, 以便于与名为CompanySizeFieldControl.ascx的ASP.NET User Control 来协同工作的. 特别地, CompanySizeFieldControl 类使用名为RenderingTemplate 的控件, 该控件定义在CompanySizeFieldControl.ascx中. 你还应该注意到在install.bat中, 还书写了命令把CompanySizeFieldControl.ascx 文件拷贝到它需要被部署的目录TEMPLATE\CONTROLTEMPLATES 之下. 正如你所看到的, CompanySizeFieldControl.ascx 中RenderingTemplate 控件的定义并不是非常复杂.

<SharePoint:RenderingTemplate ID="CompanySizeFieldControl" runat="server">
  <Template>
    <asp:DropDownList ID="CompanySizeSelector" runat="server" />
  </Template>
</SharePoint:RenderingTemplate>

现在, 我们来看看下面的CompanySizeFieldControl 的实现. 这个类别敖汉一个叫做CompanySizeSelector 的field, 它基于名为DropDownList的ASP.NET控件. 还有, 在CreateChildControls 方法中, 还有代码把这个field与定义在CompanySizeFieldControl.ascx中的DropDownList 的实例绑定了起来. 这使得这个类中的代码可以用一系列的items来实例化DropDownList控件.

The CompanySizeFieldControl Class

public class CompanySizeFieldControl : BaseFieldControl
{
    protected DropDownList CompanySizeSelector;
    protected override string DefaultTemplateName
    {
        get { return "CompanySizeFieldControl"; }
    }
    public override object Value
    {
        get
        {
            EnsureChildControls();
            return this.CompanySizeSelector.SelectedValue;
        }
        set
        {
            EnsureChildControls();
            this.CompanySizeSelector.SelectedValue = (string)this.ItemFieldValue;
        }
    }

    protected override void CreateChildControls()
    {
        if (this.Field == null || this.ControlMode == SPControlMode.Display)
            return;
        base.CreateChildControls();
        this.CompanySizeSelector =
              (DropDownList)TemplateContainer.FindControl("CompanySizeSelector");
        if (this.CompanySizeSelector == null)
            throw new ConfigurationErrorsException("Error: cannot load .ASCX file!");
        if (!this.Page.IsPostBack)
        {
            this.CompanySizeSelector.Items.AddRange(new ListItem[]
                   { new ListItem(string.Empty, null),
                     new ListItem("Mom and Pop Shop (1-20)", "1-20"),
                     new ListItem("Small Business (21-100)", "21-100"),
                     new ListItem("Medium-sized Business (101-1000)", "101-1000"),
                     new ListItem("Big Business (1001-20,000)", "1001-20000"),
                     new ListItem("Enterprise Business (over 20,000)", "20000+")});
        }
    }
}

CompanySizeFieldControl 类重写(overrides )了一个名为DefaultTemplateName的只读属性, 这个属性返回在CompanySizeFieldControl.ascx中定义的RenderingTemplate 的名字. CompanySizeFieldControl 类的基类中有代码使用这个字符串来在运行时从CompanySizeFieldControl.ascx加载RenderingTemplate.

 

你还应该检查CompanySizeFieldControl 类中被重写了的Value 属性. 内部的get方法从DropDownList 控件返回值. 内部的set方法使用基类中定义的ItemFieldValue 属性, 把这个值赋给DropDownList 控件.

 

现在你已经看过在ascx文件中的两个类和一个RenderingTemplate 是如何协同工作来提供一个custom field type的实现的了. 这个谜题的最后一部分就是让WSS识别到你已经通过在一个基于CAML的文件中添加一个Field Schema , 而引入一个新的custom field type 到服务器场中了, 这个文件会被拷贝到一个大家都熟知的地方.

 

Field types 被定义在名为fldtypes*.xml 的文件中, 这些文件必须被部署在TEMPLATE \XML 目录下. 在我们的例子里, 我们的名为CompanySize 的custom field type 的field schema , 使用被使用CAML被定义在名为fldtypes_Litware.xml的文件中. 用来定义field schema的CAML再下面列了出来. 请注意, install.bat会在你编译工程, 安装名为LitwareFieldTypes.dll 的程序集到GAC中的时候, 自动地拷贝这个文件到TEMPLATE\XML目录下. 编译工程之后, 你就能使用CompanySize 这个custom field type了.

 

A Custom Field Type Definition File

<?xml version="1.0" encoding="utf-8" ?>
<FieldTypes>
  <FieldType>
    <Field Name="TypeName">CompanySize</Field>
    <Field Name="ParentType">Text</Field>
    <Field Name="TypeDisplayName">Company Size</Field>
    <Field Name="TypeShortDescription">Company Size</Field>
    <Field Name="UserCreatable">TRUE</Field>
    <Field Name="ShowInListCreate">TRUE</Field>
    <Field Name="ShowInSurveyCreate">TRUE</Field>
    <Field Name="ShowInDocumentLibraryCreate">TRUE</Field>
    <Field Name="ShowInColumnTemplateCreate">TRUE</Field>
    <Field Name="FieldTypeClass">
      LitwareFieldTypes.CompanySizeField, LitwareFieldTypes, ...
    </Field>
    <RenderPattern Name="DisplayPattern">
      <Switch>
        <Expr>
          <Column/>
        </Expr>
        <Case Value=""></Case>
        <Default>
          <HTML><![CDATA[<span style="color:Red"><b>]]></HTML>
          <Column SubColumnNumber="0" HTMLEncode="TRUE"/>
          <HTML><![CDATA[</b></span>]]></HTML>
        </Default>
      </Switch>
    </RenderPattern>
  </FieldType>
</FieldTypes>
在custom field type被部署到服务器场中了之后, 你能够使用它来添加一个新的column到列表中, 也可以通过基于浏览器的WSS界面来创建一个新的site column. 下图展现了

CompanySize 出现在WSS秀给用户的标准页面里为列表添加一个新column的例子.

3-14-2010 2-45-32 PM 

在列表里创建了一个新的基于CompanySize 这个custom field type类型的column后, 你可以测试它的样子和行为. 下图展现了一个为基于CompanySize field type的列复制的例子. 注意, 这个custom field type渲染成一个DropDownList 控件, 其中显示用户预定义的一系列值. 尽管这个例子中, 我们在DropDownList 中使用的是hard-coded的item, 你自己写的时候可以扩展这个代码为从其他数据源获得item的值.

3-14-2010 2-49-33 PM

摘译自:

Inside Microsoft Windows SharePoint Services 3.0 第六章

原文地址:https://www.cnblogs.com/awpatp/p/1685530.html