自定义列表字段类型(2)

从这次开始,将逐步介绍如何创建一个自定义字段类型,以及通过什么样的手段来完成我们需要的功能。

随着例子从简单到复杂,所涉及的内容也有所增长,所以大致的计划流程是这样的:字段类型、xml描述文件、输入控件、值类型、自定义属性控件、自定义属性bug的解决方案、(自定义字段间的通信),大概先分为这几期吧(看来是一个任重而道远的工程……)

那么本期先通过一个最简单的自定义字段类型的例子,来看一下如何创建自定义字段类型中的字段类。

在这个例子中,我们将编写一个Email地址的字段,它可以完成Email地址的合法性验证。

首先,自定义字段类型在SharePoint Extension for Visual Studio 2005里其实是有模板的,但是我们在创建一个项目的时候却看不到它,其实它的创建流程是这样的:

先创建一个空的SharePoint解决方案:

image

然后在新建一个Item的时候,在可选的模板中就能够看到一个“Field Control”了,选择它:

image

点确定之后,我们会发现模板为我们创建出了两个文件,xxx.Field.cs和xxx.FieldControl.cs,这两个文件分别定义了字段的类和字段的输入控件。并且自动生成了一个强命名的key,使得我们可以把编译得到的dll放到GAC中。这次主要对字段类进行介绍。

在上上次中介绍过SharePoint的内置的字段类型,每一个字段类型都有自己的类(例如单行文本对应SPFieldText),这些类全部都是SPField的子类。所以,当我们编写一个自己的字段类型的时候,也需要让这个字段类型是SPField的子类,这样才能够完成字段类型的功能。但实际上,我们往往并不需要直接继承SPField,而是找一个与我们所需要的功能最接近的字段类型继承它,这样的优点就是我们可以使用这种内置字段类型的一些特殊属性(比如单行文本中的最长字符数限制等),并且能够使用内置字段类型的默认输入界面,另一个优点就是如果要直接继承SPField,要多写一个东西(但是我忘了是什么了……汗……)。

在这个例子中,Email地址的输入和单行文本非常类似,于是我们继承SPFieldText。

好,可能有人会发现了,默认由模板创建出来的这个项目中它就是继承了SPFieldText的,在我们继续之前,不妨先来看一看这默认生成的代码中都有什么东西。

我们已经看到默认的模板创建出来了Field类和FieldControl类,并且Field类继承了SPFieldText,也就是单行文本。然后在这个Field类中,我们还可以看到如下两大部分内容:

第一部分:构造函数

public EmailFieldField(SPFieldCollection fields, string fieldName)
  : base(fields, fieldName)
{
}

public EmailFieldField(SPFieldCollection fields, string typeName, string displayName)
  : base(fields, typeName, displayName)
{
}

SPFieldText并不支持不带参数的默认构造函数,所以要重载这两种构造函数,而这两种构造函数也是SPField所使用的,默认情况下直接使用相同的参数调用父类的构造函数。通过Reflector我们可以看到,在SPField的这两种构造函数中都是根据参数设置了一些初始值。因此,如果需要有一些特殊的初始值要设置,我们可以放在这个构造函数中,例如如果我们希望这个Email地址栏只在新建界面中出现,而不让用户在默认界面上修改它,我们可以在构造函数中添加:

this.ShowInEditForm = false;

我们对这两个构造函数的修改一般也仅限于此类操作了。(其实我们几乎很少需要手动去调用Field系列的构造函数,在创建一个字段时我们往往使用的是SPFieldCollection的Add方法或者AddLookup方法)

在一个自定义的字段类型中,这个构造函数是字段类唯一一个必须重载的地方,其他内容都可以不写(当然如果你其他内容都不写的话,这个字段比起它的父类来说,无非就是多了一些初始值——当你需要这么做的时候,你就可以很简单地这么干来创建一种新的字段类型。。。)

第二部分:关联的控件

在默认生成的代码中,重载了SPFieldText的一个属性叫做FieldRenderingControl。顾名思义,这个只读属性是用来返回与此字段相关联的显示/输入控件的。这部分内容我们放在下下次的内容做介绍。

在这个Email地址的例子中,我们可以直接使用SPFieldText字段类型的默认输入控件(至于显示我们可以放到xml里来定义),因此我们无需重载它,把它删掉好了(同时也可以把那个xxxx.FieldControl.cs也删掉,而且它其实就是空的……)

既然是自定义字段类型,那么必然和默认的单行文本要有所区别,在这个例子中,我们所提供的额外功能就是Email地址的验证,于是我们就需要:

第三部分:数据验证

数据验证功能一般来说都是放在输入界面里做的,但是其实我们也可以把类似的功能放到字段类中(因为我们使用的是默认输入界面)。

在SPField中,有这样一个方法我们可以重载:

public override string GetValidatedString(object value)

这个方法的目的就是根据这个字段的值(object),返回一个通过验证的字符串。其主要目的第一在于验证数据,第二在于做数据串行化(Serialization),把数据值都转换成字符串。这个方法在每次提交值的时候都会执行到,所以可以用来进行数据验证。

在重载这个方法的时候,一般我们都先需要判断一下数据是否为空,然后再做真正的自定义的数据校验。如果在校验过程中发现了不合法的数据,我们需要使用一个特殊的Exception类:SPFieldValidationException。这个异常的表现形式就是我们在填错什么东西时,字段输入控件下面会出现的那行红字。

在这个例子中,我们使用正则表达式来验证Email地址,整个函数的函数体如下:

public override string GetValidatedString(object value)
{
    if (Required && (value == null || value.ToString() == ""))
    throw new SPFieldValidationException(SPResource.GetString(Strings.MissingRequiredField));

    // Validate email format
    string emailRE = @"^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$";
    if (!Regex.IsMatch(value.ToString(), emailRE))
        throw new SPFieldValidationException("Invalid Email Address.");

    if (value == null)
        return string.Empty;
    else
        return value.ToString();
}

这个例子写到现在,功能已经完成了,这就是最简单的一个自定义字段类型的开发。当然到现在我们还不能用它,还需要写一个xml描述文件,放在下次介绍。

那么在这个字段类中,我们通常还可以写哪些内容呢?

第四部分:自定义属性

每个字段类型都有它自己特殊的一些属性,我们称之为自定义字段属性(比如单行文本的最大长度、数字的最大值最小值这样的)。

在SDK中编写自定义属性的方法中,并不需要在字段类中加什么内容,但由于那个bug的存在,在两种解决方案中,都需要在字段类中加上自己的属性。有关这一部分,也等到专门自定义属性的时候再说。

第五部分:获取字段值

在SPField中,获取一个字段的值通常有多种手段,完成不同的用途。例如刚刚介绍过的那个GetValidatedString。

有时为了完成其他一些用途,或者和我们其他的一些代码配合,可能需要重载这些方法,它们有:

public object GetFieldValue(string value)

——根据字符串的值获得真正的值类型(简单类型如double,复杂类型如SPFieldxxxxValue),可以把它理解为反串行化的过程。

public string GetFieldValueAsText(object value)

——根据值得到文本,与GetValidatedString方法不同,这个方法并不是总被执行,它主要还是用于显示。

public string GetFieldValueAsHtml(object value)

——和上面的方法类似,只不过是用Html的格式来显示,这两个方法已经在(0)里面提到过了。

public string GetFieldValueForEdit(object value)

——在编辑时获取一个字符串,其实这是一个有点奇怪的方法,因为后面我们在介绍输入控件的时候,一般都是用object作为Value的。难道Edit时的value会和一般的value不同么?我发现这个方法的重载是在SPFieldNumber里,当它设置为用百分比显示时,想一想编辑时填的值和真正的值有什么区别(30% vs 0.3),就可以理解它的意义了。

上面这些方法就不再一一进行介绍了,有兴趣的可以用Reflector看一看Microsoft.SharePoint.dll中,内置的那些字段类型是怎么写的,会有很大的帮助。

第六部分:其他

其实,上面的那些内容除了自定义属性之外,都是来自SPField的属性或者方法,当然我们也可以根据需要重写它的其他属性和方法。也可以写自己的……

言归正传,我们已经写了一个最简单的Email地址字段类,那么怎么样使用和部署?用什么方式对它进行描述?请看下期……

(未完待续)

posted on 2007-11-29 00:56  Erucy  阅读(472)  评论(0编辑  收藏  举报

导航