继续介绍内容类型架构定义所用到的XML标记
ContentTypes 元素
包含元素:ContentType, ContentTypeRef
比如:某个列表定义中的3个内容类型
Direction="$Resources:Direction;" Url="Financial Documents"
BaseType="1"
EnableContentTypes="TRUE">
<MetaData>
<ContentTypes>
<ContentTypeRef ID="0x01010012841A8869DB425cB829C3875EC558CE01">
<Folder TargetName="Forms/Document" />
</ContentTypeRef>
<ContentTypeRef ID="0x01010012841A8869DB425cB829C3875EC558CE02">
<Folder TargetName="Forms/Document" />
</ContentTypeRef>
<ContentTypeRef ID="0x0120" />
</ContentTypes>
...
</MetaData>
</List>
ContentType元素
用于定义一个内容类型。
BaseType="Text"
ID="Text"
Name="Text"
Description="Text"
DocumentTemplate="Text"
FeatureId="Text” Group="Text"
Hidden="TRUE" | "FALSE"
Inherits="TRUE" | "FALSE"
ProgId="Text"
NewDocumentControl="Text"
Overwrite="TRUE" | "FALSE
PushDownChangedResourceFilesOnly="TRUE" | "FALSE
ReadOnly="TRUE" | "FALSE"
RequireClientRenderingOnNew="TRUE" | "FALSE"
ResourceFolder="Text"
Sealed="TRUE" | "FALSE"
V2ListTemplateName="Text"
Version="Integer"
/>
其中属性:
- ID,必须,需要符合前面第二篇中所说的内容类型ID公约
- Name,必须,不操过128个字符,并且不能包含\ / : * ? “ # % < > { } | ~ &,两个连续的点(..)或其他特殊字符,如Tab
比如,SharePoint内置的“文档”内容类型的定义如下:
Name="$Resources:Document"
Group="$Resources:Document_Content_Types"
Description="$Resources:DocumentCTDesc"
V2ListTemplateName="doclib"
Version="0">
<FieldRefs>
<RemoveFieldRef ID="{67df98f4-9dec-48ff-a553-29bece9c5bf4}" Name="Attachments" /> <!-- Attachments -->
<RemoveFieldRef ID="{f1e020bc-ba26-443f-bf2f-b68715017bbc}" Name="WorkflowVersion" /> <!-- WorkflowVersion -->
<RemoveFieldRef ID="{bc91a437-52e7-49e1-8c4e-4698904b2b6d}" Name="LinkTitleNoMenu" /> <!-- LinkTitleNoMenu -->
<RemoveFieldRef ID="{82642ec8-ef9b-478f-acf9-31f7d45fbc31}" Name="LinkTitle" /> <!-- LinkTitle -->
<RemoveFieldRef ID="{ae069f25-3ac2-4256-b9c3-15dbc15da0e0}" Name="GUID" /> <!-- GUID -->
<RemoveFieldRef ID="{de8beacf-5505-47cd-80a6-aa44e7ffe2f4}" Name="WorkflowInstanceID" /> <!-- WorkflowInstanceID -->
<FieldRef ID="{5f47e085-2150-41dc-b661-442f3027f552}" Name="SelectFilename" /> <!-- SelectFilename -->
<FieldRef ID="{8553196d-ec8d-4564-9861-3dbe931050c8}" Name="FileLeafRef" Required="TRUE"/> <!-- FileLeafRef -->
<FieldRef ID="{8c06beca-0777-48f7-91c7-6da68bc07b69}" Name="Created" Hidden="TRUE" /> <!-- Created -->
<FieldRef ID="{fa564e0f-0c70-4ab9-b863-0177e6ddd247}" Name="Title" Required="FALSE" ShowInNewForm="FALSE" ShowInEditForm="TRUE"/> <!-- Title -->
<FieldRef ID="{28cf69c5-fa48-462a-b5cd-27b6f9d2bd5f}" Name="Modified" Hidden="TRUE" /> <!-- Modified -->
<FieldRef ID="{822c78e3-1ea9-4943-b449-57863ad33ca9}" Name="Modified_x0020_By" Hidden="FALSE"/> <!-- Modified_x0020_By -->
<FieldRef ID="{4dd7e525-8d6b-4cb4-9d3e-44ee25f973eb}" Name="Created_x0020_By" Hidden="FALSE" /> <!-- Created_x0020_By -->
</FieldRefs>
<XmlDocuments>
<XmlDocument NamespaceURI="http://schemas.microsoft.com/sharepoint/v3/contenttype/forms">
<FormTemplates xmlns="http://schemas.microsoft.com/sharepoint/v3/contenttype/forms">
<Display>DocumentLibraryForm</Display>
<Edit>DocumentLibraryForm</Edit>
<New>DocumentLibraryForm</New>
</FormTemplates>
</XmlDocument>
</XmlDocuments>
</ContentType
DocumentTemplate 元素
用于为内容类型指定文档模板。也就是当用户点击新建时作为模板打开的文件。
...
<DocumentTemplate TargetName="/_layouts/NewCTDoc.aspx" />
</ContentType>
需要注意得是,我们必须单独另外部署好所需的模板文件。一种比较好的办法是利用Module元素,将其包含到Feature中。
示例:还是以开头财务文档的为例子,其所对应的Feature定义如下,注意其中FieldRef的使用场景:
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<!-- Document Templates -->
<Module Name="InvoiceDocumentTemplate"
Path="FinancialDocuments"
Url="_cts/Invoice" RootWebOnly="TRUE">
<File Url="Invoice.docx" Type="Ghostable" />
</Module>
<Module Name="PurchaseOrderDocumentTemplate"
Path="FinancialDocuments"
Url="_cts/PurchaseOrder" RootWebOnly="TRUE">
<File Url="PurchaseOrder.docx" Type="Ghostable" />
</Module>
<!-- Site Columns -->
<Field ID="{060E50AC-E9C1-4D3C-B1F9-DE0BCAC300F6}"
Name="Amount"
DisplayName="Amount"
Type="Currency"
Decimals="2"
Min="0"
Required="FALSE"
Group="Financial Columns" />
<Field ID="{86811853-7E52-4515-A88D-A8FA9D450905}"
Name="Client"
DisplayName="Client Name"
Type="Text"
Required="FALSE"
Group="Financial Columns"/>
<Field ID="{1511BF28-A787-4061-B2E1-71F64CC93FD5}"
Name="DateOpened"
DisplayName="Date Opened"
Type="DateTime"
Format="DateOnly"
Required="FALSE"
Group="Financial Columns">
<Default>[today]</Default>
</Field>
<Field ID="{943E7530-5E2B-4C02-8259-CCD93A9ECB18}"
Name="CostCenter"
DisplayName="Department"
Type="Choice"
Required="FALSE"
Group="Financial Columns">
<CHOICES>
<CHOICE>Administration</CHOICE>
<CHOICE>Information</CHOICE>
<CHOICE>Facilities</CHOICE>
<CHOICE>Operations</CHOICE>
<CHOICE>Sales</CHOICE>
<CHOICE>Marketing</CHOICE>
</CHOICES>
</Field>
<!-- Site Content Types -->
<!-- Parent ContentType: Document (0x0101) -->
<ContentType ID="0x0101000728167cd9c94899925ba69c4af6743e"
Name="Financial Document"
Group="Financial Content Types"
Description="Base financial content type"
Version="0">
<FieldRefs>
<FieldRef ID="{1511BF28-A787-4061-B2E1-71F64CC93FD5}" Name="DateOpened" DisplayName="Date" Required="TRUE"/>
<FieldRef ID="{060E50AC-E9C1-4D3C-B1F9-DE0BCAC300F6}" Name="Amount" DisplayName="Amount" Required="FALSE"/>
</FieldRefs>
</ContentType>
<!-- Parent ContentType: Financial Document -->
<ContentType ID="0x0101000728167cd9c94899925ba69c4af6743e01"
Name="Invoice"
Group="Financial Content Types"
Description="Used for creating customer invoices"
Inherits="TRUE"
Version="0">
<FieldRefs>
<FieldRef ID="{fa564e0f-0c70-4ab9-b863-0177e6ddd247}" Name="Title" DisplayName="Service" Required="TRUE" Sealed="TRUE"/>
<FieldRef ID="{86811853-7E52-4515-A88D-A8FA9D450905}" Name="Client" DisplayName="Client Name" Required="TRUE"/>
</FieldRefs>
<DocumentTemplate TargetName="Invoice.docx" />
</ContentType>
<!-- Parent ContentType: Financial Document -->
<ContentType ID="0x0101000728167cd9c94899925ba69c4af6743e02"
Name="PurchaseOrder"
Group="Financial Content Types"
Description="Used for creating purchase orders"
Inherits="TRUE"
Version="0">
<FieldRefs>
<FieldRef ID="{fa564e0f-0c70-4ab9-b863-0177e6ddd247}" Name="Title" DisplayName="Item" Required="TRUE" Sealed="TRUE"/>
<FieldRef ID="{943E7530-5E2B-4C02-8259-CCD93A9ECB18}" Name="CostCenter" DisplayName="Department" Required="TRUE"/>
</FieldRefs>
<DocumentTemplate TargetName="PurchaseOrder.docx"/>
</ContentType>
</Elements
Folder元素
用于指定内容类型的资源文件夹的文件夹相对路径。
FieldRefs 元素
用于包含FieldRef 栏的引用。可以引用已存在的栏或者在同一个Feature中创建的新栏。可以引用父内容类型的栏,并覆盖栏的部分属性。可覆盖的属性包括:
- 显示名
- 升级与降级相关的XML属性
- 栏是否为只读,必需,隐藏
其中的ID,Name,DisplayName,Required是必须的。即无论与栏定义是否相同都必须指定。其中ID应该是一个GUID,包括大括号,并且是大小写敏感的。
RemoveFieldRef 要从父内容类型中移除的栏。只需要ID,其他的属性都将被SharePoint忽略。
内置的栏的ID值可以从fieldswss.xml(位于%ProgramFiles%\Common Files\Microsoft Shared\web server extensions\14\TEMPLATE\FEATURES\fields)中查看。同时还可以用来学习栏的定义。
XmlDocuments和XmlDocument 元素
用于在内容类型中包含自定义信息。可用于对象模型编程时访问。
SharePoint自身包含了两个XmlDocument,用于内容类型的自定义表单模板和客户端重定向。
- FormTemplates架构
- FormUrls架构
例如,通过自定义信息指定打开内容类型所需的表单模板
<XmlDocument NamespaceURI="http://schemas.microsoft.com/sharepoint/v3/contenttype/forms">
<FormTemplates xmlns="http://schemas.microsoft.com/sharepoint/v3/contenttype/forms">
<Display>DocumentLibraryForm</Display>
<Edit>DocumentLibraryForm</Edit>
<New>DocumentLibraryForm</New>
</FormTemplates>
</XmlDocument>
</XmlDocuments>
FormTemplates架构
用于指定UI中列表条目的查看,新建与编辑表单模板。包括以下元素:
- FormTemplates根节点,其xmlns必是http://schemas.microsoft.com/sharepoint/v3/contenttype/forms
- Display 指定自定义查看表单模板
- Edit 指定自定义编辑表单模板
- New 指定自定义新建表单模板
这里指定的表单模板是指列表对应表单页面中央的.asmx部分。表单模板的名称必须是一个已存在的渲染模板(渲染模板位于%ProgramFiles%\Common Files\Microsoft Shared\web server extensions\14\TEMPLATE\CONTROLTEMPLATES下的一个.ascx文件中)
如果没有在内容类型定义中指定表单模板,则会使用SharePoint的默认值。
以下为默认的文档内容类型的表单模板
<Display>DocumentLibraryForm</Display>
<Edit>DocumentLibraryForm</Edit>
<New>DocumentLibraryForm</New>
</FormTemplates>
以下为默认的列表项的表单模板
<Display>ListForm</Display>
<Edit>ListForm</Edit>
<New>ListForm</New>
</FormTemplates>
FormUrls架构
用于为内容类型指定客户端重定向到另外的查看,编辑,新建表单页面。包括以下内容:
- FormUrls根元素,其xmlns必是http://schemas.microsoft.com/sharepoint/v3/contenttype/forms/url
- Display 可选,指定自定义查看表单的地址
- Edit 可选,指定自定义编辑表单的地址
- New 可选,指定自定义新建表单的地址
表单页是一个.aspx页面,用于整个替换SharePoint默认的页面。包括SharePoint的显示框架,如顶部,左侧导航等等。因此在自定义的表单页上,我们要根据需要重建出相应的一些内容。
地址是相对于内容类型根目录而言的。
如果没有指定,SharePoint将使用默认值。
<Display>Forms/mydisplayform.aspx</Display>
<Edit>Forms/myeditform.aspx</Edit>
<New>Forms/myuploadform.aspx</New>
</FormUrls>
在网站定义中指定内容类型
在网站定义中指定内容类型,可以在用户每次创建该类型的网站时,让SharePoint默认添加上该内容类型。
首先,需要在另一个Feature中创建该内容类型。然后,通过站点定义文件Onet.xml内的Configuration元素中引用引用该Feature。可以是在SiteFeatures元素内,也可以是在WebFeatures元素内。
注意:对SharePoint内置的站点定义修改Onet.xml是不被支持的。因此,最好先创建一个自定义站点定义。
<Feature ID="00BFEA71-1C5E-4A24-B310-BA51C3EB7A57" />
<Feature ID="695B6570-ACDC-4A8E-8545-26EA7FC1D162" />
</SiteFeatures>
<WebFeatures>
<Feature ID="00BFEA71-4EA5-48D4-A4AD-7EA5C011ABE5" />
<Feature ID="00BFEA71-E717-4E80-DEAF-D0C71B360101" />
</WebFeatures>
在列表定义中添加内容类型
添加前必须确认列表被配置为支持内容类型。
第一个要检查的是列表所使用的列表模板的ListTemplate元素有一个DisallowContentTypes属性。如果值为TRUE,则列表不支持内容类型。如果值为FALSE或未设置,则列表支持内容类型。
第二个要检查的是列表实例是否启用了内容类型。在定义该列表实例的Schema.xml中有一个List元素。该元素包含一个必要的属性——EnableContentTypes,该属性值必须为TRUE。这等同于在UI中的列表设置,高级设置中选择了允许内容类型(可参考第三篇中的内容)。
可以作为列表定义的一部分添加列表内容类型。在列表定义的ContentTypes元素内,我们可以引用已有的网站内容类型(通过包含一系列ContentTypeRef元素,每个元素只需要一个ID属性,设置为所添加的内容类型的ID),也可以创建新的内容类型。这时,我们新建的内容类型仅在该列表定义的实例中有效。新内容类型并不属于网站内容类型集合或其他列表。
我们所引用的网站内容类型必须位于列表的范围内——即相同的网站层次或更高。
注意:当SharePoint 创建一个列表实例时,它将仅仅包含基类列表架构或该列表架构中的栏。如果我们在列表架构中引用了一个网站内容类型,该内容类型引用了一些并不包含在基类列表架构或该列表架构中的网站栏,则这些栏将不会被包含进来。想要包含,必须先在列表架构中对其进行定义。
<MetaData>
<ContentTypes>
<ContentTypeRef ID="0x01060062efcfca3f4d4036a0c54ed20108fa2e" />
</ContentTypes>
...
</MetaData>
</List>
示例:创建一个自定义字段,内容类型,列表定义和列表实例
现在将实际动手使用VS2010创建一个名为“病人姓名”的自定义栏,并创建一个包含该栏的内容类型。然后,创建一个列表定义包含该内容类型。最后,创建基于该列表定义创建一个列表实例,并从中找到上面创建的内容类型和栏。
新建空白SharePoint项目
由于列表定义无法作为沙箱解决方案部署,所以这里必须选择服务器场部署。
添加空元素
编辑Elements.xml文件
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<Field ID="{FF958DD5-5ABD-405D-A83E-811FA18853F9}"
Type="Note"
Name="PatientName"
DisplayName="病人姓名"
Group="医疗信息">
</Field>
</Elements>
如果是首次在该站点上调试,VS会帮我们修改web.config,启用调试设置。
执行结果
新建内容类型
选择父内容类型
在自动生成的Elements.xml文件中,添加上面的栏的引用
执行结果
点击进去,看到已经添加了栏。并且继承了父内容类型。
选择基于内容类型创建的列表定义。
使用刚刚添加的内容类型
自动创建的列表模板定义
自动创建的列表架构定义,其中已经自动包含了上面的内容类型
执行结果
注意:
在测试环境下发现回收解决方案后列表实例不会被删除,但是访问时会报错。成为垃圾。
解决办法是在回收前先删除该列表。
SharePoint2010内容类型剖析系列——(完)