如何:自定义列表视图中字段的呈现方式

上次修改时间: 2011年3月29日

适用范围: SharePoint Foundation 2010

本文内容
列表视图上自定义字段呈现概述
为自定义字段定义自定义呈现
示例:自定义货币字段

本主题说明您可以如何定义自定义字段在列表视图上的呈现方式。

列表视图上自定义字段呈现概述

Microsoft SharePoint Foundation 使用 XSLT 样式表来呈现列表视图。(有关系统的讨论,请参阅 XSLT 列表视图呈现系统概述。)列表以 HTML 表的形式呈现,字段值由位于 %ProgramFiles%\Common Files\Microsoft Shared\web server extensions\14\TEMPLATE\LAYOUTS\XSL 的 fldtypes.xsl 文件中的简单 XSLT 模板呈现到适当的表单元格中。该文件中有很多可用于呈现字段值的模板。使用哪一个模板取决于若干因素,其中最重要的因素是由 SPFieldType 枚举定义的字段类型。例如,用于 Number 字段的模板为 FieldRef_Number_body,而用于 Text 字段的模板为 FieldRef_Text_body。

备注

字段类型与模板之间 存在一对一的对应关系。例如,计算字段对应于好几个不同的模板,而 FieldRef_Number_body 模板既可用于 Currrency() 字段,也可用于 Number 字段。

例如,下面是 FieldRef_Text_body 模板。

<xsl:template name="FieldRef_Text_body" ddwrt:dvt_mode="body" match ="FieldRef" mode="Text_body">
  <xsl:param name="thisNode" select="."/>
  <xsl:choose>
    <xsl:when test="@AutoHyperLink='TRUE'">
      <xsl:value-of select="$thisNode/@*[name()=current()/@Name]" disable-output-escaping ="yes"/>
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="$thisNode/@*[name()=current()/@Name]"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

传递到此模板的 thisNode 参数由包含来自列表的项(最多为每页允许的最大数目)的 dsQueryResponse 标记组成。有关此标记的示例,请参阅 XSLT 转换中的输入和结果节点树示例

另请注意,模板将根据字段是否定义为自动将类似 URL 的字符串格式化为 HTML <a> 链接形式来进行分支。如果答案为是,则当 XSLT 处理器为字段呈现 HTML 时,它不会 将类似"<"和"&"的有意义字符替换为其字符实体等效项(&lt; 和 &amp;),而符合标准的 XSLT 处理器默认情况下通常会做此替换。除了此处比较复杂之外,模板只是使用以下代码行发出字段值。

<xsl:value-of select="$thisNode/@*[name()=current()/@Name]"/>

由于此代码行几乎出现在所有呈现 XSLT 模板中的字段中,因此有必要来仔细分析一下。XPath 中的第一步是标识要呈现其值的节点,它只不过是对 thisNode 参数的引用,因此将相对于此参数中的标记的根来解释其余的步骤。下一个步骤是 /@*(在应用谓词之前),它引用根及其后代的所有属性。因此在此例中,它将引用 thisNode 中的所有元素的所有属性。谓词修饰的 [name()=current()/@Name] 进一步缩小了选择范围。"="左侧是 XSLT name() 函数,它表示由"$thisNode/@*"部分生成的序列中的某个节点的名称。也就是说,它表示 thisNode 的某个元素中的某个属性的名称。如果我们将此函数应用于 XSLT 转换中的输入和结果节点树示例中的示例 thisNode,我们将会看到,此示例中的某些属性以列表项字段的内部名称命名;例如,Attachments、Title 和自定义字段 ISBN。"="右侧是对源节点树中的当前节点的 Name 属性的引用:current()/@Name。由于此模板是使用 match ="FieldRef" 声明的,因此它只应用于 FieldRef 元素;因而 current() 函数引用一个 FieldlRef 元素。因此,整个 xsl:value-of 元素表示的意思是"发出 thisNode 中其名称与源节点树中的当前 FieldRef 的名称相同的属性的值。"

因此,当处理示例源节点树的 Title FieldRef 时,XSLT 处理器将为其发出 thisNode 标记中的当前 Row 元素的 Title 属性值。(对于第一行,这就是"真理")。同样,当处理源节点树("0-262-61107-4")的 ISBNFieldRef 时,XSLT 处理器将呈现同一 Row 的 ISBN 属性值。

在大多数情况下,自定义字段将获得的默认呈现方式(主要由字段基类型确定)刚好就是您想要的。例如,对于文本字段这种情况,值以纯文本形式呈现在 HTML 表的适当单元格内。如果您希望自定义字段以特殊方式呈现,则必须使用 XSLT 样式表定义它的呈现方式。下一节将说明如何执行此操作。

为自定义字段定义自定义呈现

下面的过程说明如何创建自定义 XSLT 样式表来呈现自定义字段类型。

创建自定义 XSLT 样式表以便进行字段呈现

  1. 创建一个扩展名为"xsl"的文本文件。该文件必须按 fldtypes_*.xsl 模式命名,其中"*"是允许的文件名字符组成的任意字符串。请考虑使用自定义字段的名称,如 fldtypes_ISBN.xsl。如果您将具有多个自定义 XSLT 样式表,请考虑使用您的公司名称(如 fldtypes_Contoso.xsl),并将这些样式表全部包括在同一个文件中。避免使用可能由另一个解决方案提供商使用的字符串。

  2. 向文件中添加以下样式表声明。

    <xsl:stylesheet xmlns:x="http://www.w3.org/2001/XMLSchema"
                    xmlns:d="https://schemas.microsoft.com/sharepoint/dsp"
                    version="1.0"
                    exclude-result-prefixes="xsl msxsl ddwrt"
                    xmlns:ddwrt="https://schemas.microsoft.com/WebParts/v2/DataView/runtime"
                    xmlns:asp="https://schemas.microsoft.com/ASPNET/20"
                    xmlns:__designer="https://schemas.microsoft.com/WebParts/v2/DataView/designer" 
                    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                    xmlns:msxsl="urn:schemas-microsoft-com:xslt"
                    xmlns:SharePoint="Microsoft.SharePoint.WebControls"
                    xmlns:ddwrt2="urn:frontpage:internal">
    
    
    </xsl:stylesheet>
    
  3. 在 %ProgramFiles%\Common Files\Microsoft Shared\web server extensions\14\TEMPLATE\LAYOUTS\XSL 中打开名为 fldtypes.xsl 的文件,并找到默认情况下用于呈现您的字段的模板。例如,如果字段的基类型为货币类型,则模板是 FieldRef_Number_body。将模板复制为您的 xsl:stylesheet 元素的子级。下面是使用 FieldRef_Number_body 模板的示例。

    <xsl:stylesheet > <!-- stylesheet attributes omitted for brevity -->
    
      <xsl:template name="FieldRef_Number_body" ddwrt:dvt_mode="body" match="FieldRef" mode="Number_body">
        <xsl:param name="thisNode" select="."/>
        <xsl:choose>
          <xsl:when test="$FreeForm">
            <xsl:call-template name="FieldRef_ValueOf_DisableEscape">
              <xsl:with-param name="thisNode" select="$thisNode"/>
            </xsl:call-template>
          </xsl:when>
          <xsl:otherwise>
            <div align="right">
              <xsl:call-template name="FieldRef_ValueOf_DisableEscape">
                <xsl:with-param name="thisNode" select="$thisNode"/>
              </xsl:call-template>
            </div>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:template>
    
    </xsl:stylesheet>
    
  4. 从 xsl:template 元素中删除 name 属性(在此例中为 name="FieldRef_Number_body")。另外,删除 ddwrt:dvt_mode 属性(如果存在)。

  5. 更改 match 属性,以便模板只与具有自定义字段的整个内部名称的字段匹配。您使用指定 FieldRef 元素的 Name 属性的必需值的 XSLT 谓词执行此操作。例如,假定您具有一个其内部名称为"Net_x0020_Profit_x002f_Loss"的"Net Profit/Loss"(净利润/损失)字段,您的模板开始标记现在应如下所示。

    <xsl:template match="FieldRef[@Name='Net_x0020_Profit_x002f_Loss']" mode="Number_body">
    

    这样可确保您 自定义您的自定义字段类型的呈现,而不是以货币或数字类型为基类型的所有字段。

  6. 编辑并添加模板的标记以产生您希望的呈现效果。有关具体示例,请参阅下面一节。

  7. 保存 fldtypes_*.xsl 文件并将其复制到所有服务器上的 %ProgramFiles%\Common Files\Microsoft Shared\web server extensions\14\TEMPLATE\LAYOUTS\XSL 中。

  8. 重置 Web 应用程序以便重新加载 %ProgramFiles%\Common Files\Microsoft Shared\web server extensions\14\TEMPLATE\LAYOUTS\XSL 中的文件。您的自定义文件将重写任何内置文件。

示例:自定义货币字段

作为第 6 步的详细示例,这一节将说明如何将"Net Profit/Loss"(净利润/损失)字段中的负数值呈现为红色。在执行步骤 5 之后,您的模板应如下所示。

<xsl:stylesheet > <!-- stylesheet attributes omitted for brevity -->

  <xsl:template match="FieldRef[@Name='Net_x0020_Profit_x002f_Loss']" mode="Number_body">
    <xsl:param name="thisNode" select="."/>
    <xsl:choose>
      <xsl:when test="$FreeForm">
        <xsl:call-template name="FieldRef_ValueOf_DisableEscape">
          <xsl:with-param name="thisNode" select="$thisNode"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <div align="right">
          <xsl:call-template name="FieldRef_ValueOf_DisableEscape">
            <xsl:with-param name="thisNode" select="$thisNode"/>
          </xsl:call-template>
        </div>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

</xsl:stylesheet>

首先请注意依赖于 FreeForm 参数的测试结果的默认呈现分支。如果源节点树中的 Toolbar 元素的 Type 属性为"FreeForm",则此测试返回 true。如果该属性值为"Standard"或者该属性根本不存在,则该模板将添加 HTML 标记以使字段值在其单元格内右对齐。(有关源节点树及其 Toolbar 元素的示例,请参阅 XSLT 转换中的输入和结果节点树示例。另请参阅 Toolbar Element (View)获取详细信息。)由于无论工具栏类型如何,负值都应是红色的,因此必须在两个分支中更改您的标记。

另请注意,该模板会调用另一个名为 FieldRef_ValueOf_DisableEscape 的模板来实际呈现值。后一个模板也位于 fldtypes.xsl 中,定义如下。

<xsl:template name="FieldRef_ValueOf_DisableEscape" ddwrt:dvt_mode="body">
  <xsl:param name="thisNode" select="."/>
  <xsl:value-of disable-output-escaping="yes" select="$thisNode/@*[name()=current()/@Name]" />
</xsl:template>

如示例中所示,与使用 <xsl:value-of select="$thisNode/@*[name()=current()/@Name]" /> 行呈现字段值的标准字段呈现模板相比,此模板的唯一不同之处在于它增加了属性 disable-output-escaping="yes",本主题前面已对此进行了说明。

在 <xsl:when test="$FreeForm"> 元素内,添加 choose-when-otherwise 结构并将对 FieldRef_ValueOf_DisableEscape 模板的现有调用移到 <xsl:otherwise> 元素中,如以下示例所示。

<xsl:when test="$FreeForm">
  <xsl:choose> 
    <when test=""> 

    </when> 
    <otherwise>
        <xsl:call-template name="FieldRef_ValueOf_DisableEscape">
          <xsl:with-param name="thisNode" select="$thisNode"/>
        </xsl:call-template>
    </otherwise> 
  </choose>
</xsl:when>

只要当前 Net_x0020_Profit_x002f_Loss 字段的值为负(即,每当值小于零时),test 值就应为 true。您已经看到,$thisNode/@*[name()=current()/@Name] 计算结果为当前字段。但是,SharePoint Foundation 中的货币字段甚至在应用任何 XSLT 格式之前便已进行低级格式化。具体来说,负的货币值用括号表示,而不是用减号表示。例如,损失 $497,882.87 表示为 ($497,882.87) 而不是 -$497,882.87。这将引起问题,因为 XSLT 处理器将所有括号表达式都视为大于 0,因此您不能直接将 $thisNode/@*[name()=current()/@Name] 的值与零进行比较。幸运的是,对于货币字段类型,SharePoint Foundation 为 thisNode 参数中的标记添加另外一种形式的字段值来作为简单的双精度类型值,此双精度类型值为负时将用减号表示。具体而言,这种形式是与 Net_x0020_Profit_x002f_Loss 属性同名的 Row 元素属性的值(只是在属性名称结尾追加了一个".")。例如,比较 XSLT 转换中的输入和结果节点树示例中的"thisNode"示例中的 Row 元素的"Retail_x0020_Price"和"Retail_x0020_Price."属性。

使用这个以点结尾的名称的属性测试是否为负值。test 表达式应如下所示。

<xsl:when test="$thisNode/@*[name()=concat(current()/@Name, '.')] &lt; 0">
提示提示

必须使用"&lt;"而不是"<",因为 XSLT 处理器认为后者应出现在元素开头。如果您愿意,您可以颠倒操作数,这样您就可以使用简单的">"号:"0 > $thisNode/@*[name()=concat(current()/@Name, '.')]"。

现在,在内部 when 结构中,复制对 FieldRef_ValueOf_DisableEscape 模板的调用,但将其放在将使用红色显示值的 HTML 文本中。下面显示了外部的 when 结构现在的样子。

<xsl:when test="$FreeForm">
  <xsl:choose> 
    <xsl:when test="$thisNode/@*[name()=concat(current()/@Name, '.')] &lt; 0"> 
      <span style="color:red">
        <xsl:call-template name="FieldRef_ValueOf_DisableEscape">
          <xsl:with-param name="thisNode" select="$thisNode"/>
        </xsl:call-template>
      </span>
    </xsl:when> 
    <xsl:otherwise>
      <xsl:call-template name="FieldRef_ValueOf_DisableEscape">
        <xsl:with-param name="thisNode" select="$thisNode"/>
      </xsl:call-template>
    </xsl:otherwise> 
  </xsl:choose>
</xsl:when>

如上所述,无论工具栏的类型如何,该字段都应以同一种颜色呈现,因此整个内部 choose 结构应成为外部 choose 结构的 otherwise 部分中的 div 元素的组成内容。这样做将生成以下内容作为模板定义。

<xsl:template match="FieldRef[@Name='Net_x0020_Profit_x002f_Loss']" mode="Number_body">
    <xsl:param name="thisNode" select="."/>

  <xsl:choose>
    <xsl:when test="$FreeForm">
      <xsl:choose> 
        <xsl:when test="$thisNode/@*[name()=concat(current()/@Name, '.')] &lt; 0"> 
          <span style="color:red">
            <xsl:call-template name="FieldRef_ValueOf_DisableEscape">
              <xsl:with-param name="thisNode" select="$thisNode"/>
          </xsl:call-template>
          </span>
        </xsl:when> 
        <xsl:otherwise>
          <xsl:call-template name="FieldRef_ValueOf_DisableEscape">
            <xsl:with-param name="thisNode" select="$thisNode"/>
          </xsl:call-template>
        </xsl:otherwise> 
      </xsl:choose>
    </xsl:when>
    <xsl:otherwise>    
      <div align="right">
        <xsl:choose> 
          <xsl:when test="$thisNode/@*[name()=concat(current()/@Name, '.')] &lt; 0"> 
            <span style="color:red">
              <xsl:call-template name="FieldRef_ValueOf_DisableEscape">
                <xsl:with-param name="thisNode" select="$thisNode"/>
            </xsl:call-template>
            </span>
          </xsl:when> 
          <xsl:otherwise>
            <xsl:call-template name="FieldRef_ValueOf_DisableEscape">
              <xsl:with-param name="thisNode" select="$thisNode"/>
            </xsl:call-template>
          </xsl:otherwise> 
        </xsl:choose>
      </div>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template

如果通过使用 XSLT 变量和参数并嵌套模板来封装重复部分,则可生成更易于维护的模板定义。下面是使用这些技术的样式表的一种形式。

<xsl:stylesheet xmlns:x="http://www.w3.org/2001/XMLSchema"
                xmlns:d="https://schemas.microsoft.com/sharepoint/dsp"
                version="1.0"
                exclude-result-prefixes="xsl msxsl ddwrt"
                xmlns:ddwrt="https://schemas.microsoft.com/WebParts/v2/DataView/runtime"
                xmlns:asp="https://schemas.microsoft.com/ASPNET/20"
                xmlns:__designer="https://schemas.microsoft.com/WebParts/v2/DataView/designer" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:msxsl="urn:schemas-microsoft-com:xslt"
                xmlns:SharePoint="Microsoft.SharePoint.WebControls"
                xmlns:ddwrt2="urn:frontpage:internal">

  <xsl:template match="FieldRef[@Name='Net_x0020_Profit_x002f_Loss']" mode="Number_body">
    <xsl:param name="thisNode" select="."/>
    
    <xsl:variable name="FieldValue">   
      <xsl:call-template name="FieldRef_ValueOf_DisableEscape">
        <xsl:with-param name="thisNode" select="$thisNode" />
      </xsl:call-template>
    </xsl:variable>
           
    <xsl:variable name="ValueIsNegative">
      <xsl:value-of select="$thisNode/@*[name()=concat(current()/@Name, '.')]  &lt; 0" />
    </xsl:variable>
    
    <xsl:choose>
      <xsl:when test="$FreeForm">
        <xsl:call-template name="RedWhenNegative_ElseBlack" >  
             <xsl:with-param name="thisNode" select="$thisNode" />
             <xsl:with-param name="ValueIsNegative" select="$ValueIsNegative" />
               <xsl:with-param name="FieldValue" select="$FieldValue" />
          </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>    
        <div align="right">
          <xsl:call-template name="RedWhenNegative_ElseBlack" >  
        <xsl:with-param name="thisNode" select="$thisNode" />
        <xsl:with-param name="ValueIsNegative" select="$ValueIsNegative" />
        <xsl:with-param name="FieldValue" select="$FieldValue" />
              </xsl:call-template>
        </div>
      </xsl:otherwise>
    </xsl:choose>
    
  </xsl:template>
  
  <xsl:template name="FieldValueInRed">
    <xsl:param name="thisNode" select="." />
    <xsl:param name="FieldValue" select="." />
    
    <span style="color:red">
      <xsl:value-of select="$FieldValue" />
    </span>
    
  </xsl:template>
  
  <xsl:template name="RedWhenNegative_ElseBlack">
    <xsl:param name="thisNode" select="." />
    <xsl:param name="ValueIsNegative" select="." />
    <xsl:param name="FieldValue" select="." />
    
    <xsl:choose> 
      <xsl:when test="$ValueIsNegative='true'">
          <xsl:call-template name="FieldValueInRed">
            <xsl:with-param name="thisNode" select="$thisNode" />
                <xsl:with-param name="FieldValue" select="$FieldValue" />
          </xsl:call-template>      
      </xsl:when> 
      <xsl:otherwise>
        <xsl:value-of select="$FieldValue" />
      </xsl:otherwise> 
    </xsl:choose>

  </xsl:template>
  
</xsl:stylesheet>

图 1 说明了字段在列表上的显示方式。

图 1:负值用红色显示的货币字段

负值显示为红色的货币列。

请参阅

任务

演练:创建自定义字段类型

概念

自定义字段类型