设为首页 收藏本站
查看: 843|回复: 0

[经验分享] SharePoint:扩展DVWP

[复制链接]

尚未签到

发表于 2015-9-29 08:20:13 | 显示全部楼层 |阅读模式
  Richard问了一个很棒的问题:“你是否在设置insert链接的时候遇到过无匹配项( no matching items )的模版?”
  是的, 我在使用DVWP时遇到过相同的问题。当列表为空时调用特定的模版,这绝对是个bug。
  解决的方法是在SPD的设计视图中,勾选“显示示例数据(Show sample data)” ,来告诉 SPD 模拟有数据的情况。这样至少可以允许我们处理该链接了。在实际情况下页面进行渲染时,还需要进行一点稍复杂的处理。看来我需要为这个系列写一个增篇了。 ;)
  I’ll do that.
  现在我们就开始。

拨开外壳
  打开 editinsert 模版非常容易,只需要勾选一些选框就行。然而, SharePoint Designer (SPD) 使底层的XSL发生了重大变化:添加了变量和参数,修改一些已有变量的值,添加新的模版和条件格式,等等。
  变量
  dvt_1_automode 是一个变量,它告诉 DVWP 是否要绘制 edit 和/或delete 链接。 0 = 否; 1 = 是。打开 edit 和/或 delete 会将其设置为1。
  如果edit template 被打开,一个新的参数会创建出来:dvt_1_form_editkey。如果 insert 模版被打开,会创建 dvt_1_form_insertmode 。 这两个参数会在点击相应的editinsert 链接时通过 ParameterBindings 传递给该页面。



<xsl:variable name="dvt_1_automode">0</xsl:variable>

  …变成…
  




<xsl:param name="dvt_1_form_editkey" />
<xsl:param name="dvt_1_form_insertmode" />
<xsl:variable name="dvt_1_automode">1</xsl:variable>

  





在主模版dvt_1里,, 当 dvt_RowCount = 0,或者 RowLimit = 0时,IsEmpty 变量都被修改为 true 。





<xsl:variable name="IsEmpty" select="$dvt_RowCount = 0" />


…变成…





<xsl:variable name="IsEmpty" select="$dvt_RowCount = 0 or $RowLimit = 0" />



设计
首先要通过SPD进行的一个设计上的修改是:通过清空th标记的nowrap属性来允许列头折行。



<th class="ms-vh" nowrap="nowrap">Location</th>
<th class="ms-vh" nowrap="nowrap">Group</th>

…变成…



<th class="ms-vh" nowrap="">Location</th>
<th class="ms-vh" nowrap="">Group</th>

接下来的一个设计上的变更是设置一个条件,通过检验该条件来确定哪个模板会被调用。如果我们不是在插入模式中,它会调用dvt_1.body,传递给它一些行用于显示。然后是dvt_1.rowinsert,传递dvt_1_form_insertmode,决定是渲染插入数据的表单还是只是输出一个插入链接。
然后它会传递ShowNavigationShowFormActions 参数给dvt_1.commandfooter 模版,从而添加 X – Y 分页链接到页脚部分。



<xsl:with-param name="ShowNavigation">
     <xsl:if test="not($dvt_1_form_insertmode = '1')">1</xsl:if>
</xsl:with-param>
<xsl:with-param name="ShowFormActions">
    <xsl:if test="($dvt_1_automode = '0' and $dvt_1_form_insertmode)">1</xsl:if>
</xsl:with-param>

因此,这两个参数也被添加到了dvt_1.commandfooter模板,并且添加了相关的一些元素,用来在需要时显示他们。
DSC0000.png

新的模版

在默认的DVWP中, dvt_1.body 模版会遍历所有返回回来的行,为每一行都调用一次dvt_1.rowview 模版。
在更新后的版本中,它仍然会遍历所有的行,但是会检查每一行的dvt_1_form_editkey 是否与该行的ID相匹配。如果是,dvt_1.rowedit 模版会被调用,并传递该行的位置。对与剩下的所有行,会调用 dvt_1.rowview





<xsl:call-template name="dvt_1.rowview" />


…变为…



<xsl:choose>
     <xsl:when test="$dvt_1_form_editkey = ddwrt:EscapeDelims(string(@ID))">
        <xsl:call-template name="dvt_1.rowedit">
             <xsl:with-param name="Pos" select="concat('_', position())" />
         </xsl:call-template>
     </xsl:when>
     <xsl:otherwise>
         <xsl:call-template name="dvt_1.rowview" />
     </xsl:otherwise>
</xsl:choose>


当然,edit 模版(dvt_1.rowedit) 也要被添加到页面中。(有关使用edit模版的更多信息,请参考扩展DVWP的第26部分:修改edit模版)因此insert 模版大致如下所示:


…becomes…




<xsl:template name="dvt_1.rowinsert">
    <xsl:param name="IsInsertMode" />
    <xsl:variable name="Pos">_new</xsl:variable>
    <tr>
        <xsl:choose>
            <xsl:when test="$IsInsertMode = '1'">
                <xsl:if test="$dvt_1_automode = '1'" ddwrt:cf_ignore="1">
                    <td class="ms-vb" width="1%" nowrap="nowrap">
                        <xsl:call-template name="dvt_1.automode">
                            <xsl:with-param name="KeyField">ID</xsl:with-param>
                            <xsl:with-param name="KeyValue" select="ddwrt:EscapeDelims(string(@ID))" />
                            <xsl:with-param name="Mode">insert</xsl:with-param>
                        </xsl:call-template>
                    </td>
                </xsl:if>
                <td class="ms-vb">
                    <SharePoint:FormField runat="server" id="ff1{$Pos}" ControlMode="New" FieldName="YourField" {code} />
                    <SharePoint:FieldDescription runat="server" id="ff1description{$Pos}" FieldName="YourField" ControlMode="Edit" />
                </td>
                <td class="ms-vb">
                    //The next column
                </td>
                .
                .
                .
            </xsl:when>
            <xsl:otherwise>
                <td class="ms-vb" colspan="99">
                    <a href="javascript: {ddwrt:GenFireServerEvent('__cancel;dvt_1_form_insertmode={1}')}">insert</a>
                </td>
            </xsl:otherwise>
        </xsl:choose>
    </tr>
</xsl:template>


注意其中的第6行, IsInsertMode 变量决定了数据控件是否渲染,或者只是输出insert 行。

进一步的修改

在 SPD里,当我们首次把DVWP添加到页面上时,会有一个链接可以让我们设置没有匹配项时所显示的文字。

DSC0001.png
  Now, how do we display the insert link?
  Option 1. Since the empty template is being called, we could simply add the insert link to that template as well. In an STP discussion with Richard, Matt Bramer suggested adding the link below the dvt_ViewEmptyText.


SPD 会链接到数据视图属性对话框
当然我们也可以直接打开数据视图属性对话框,之前我们也曾用它来修改直接编辑选项。其中有一项可以设置当没有找到匹配的数据时所显示的文字,这里直接输入一些类似“该视图中没有项目”的文字即可。
DSC0002.png


当通过SPD的链接打开该对话框时,会自动选中选择框并填充一些默认的文字


但,这也正是会出现问题的地方。
当SPD 添加上面的文本后,它会跳过输出insert链接的 insert 模版。

DSC0003.png


噢。Insert链接没了!
重返核心

因此,让我们分析一下究竟是什么原因导致的这个问题,并试图对其进行修复。
首先,SPD并没有创建其他的变量,当dvt_RowCount = 0时 dvt_IsEmpty 被设为true。接下来在dvt_1模版的主table外包装了一层xsl:choose块。




<table border="0" width="100%" cellpadding="2" cellspacing="0">
.
.
.

  
…变为…



<xsl:variable name="dvt_IsEmpty" select="$dvt_RowCount = 0" />
    <xsl:choose>
        <xsl:when test="$dvt_IsEmpty">
            <xsl:call-template name="dvt_1.empty" />
        </xsl:when>
        <xsl:otherwise>
            <table border="0" width="100%" cellpadding="2" cellspacing="0">
            .
            .
            .


换句话说,如果列表为空,主table就不会渲染;直接进入dvt_1.empty 模版,它如下所示:



<xsl:template name="dvt_1.empty">
   <xsl:variable name="dvt_ViewEmptyText">There are no items to show in this view.</xsl:variable>
   <table border="0" width="100%">
      <tr>
         <td class="ms-vb">
            <xsl:value-of select="$dvt_ViewEmptyText" />
         </td>
      </tr>
   </table>
</xsl:template>

其中 insert 模版和所有其他的东西一样都被跳过了。这的确不是我们所期望的。


修复它

这就是 SharePoint。里面有不止一种解决问题的方式。
有一点是肯定的,那就是我们必须在列表为空的情况下进入insert模式,使得SharePoint渲染出insert表单来。当点击insert链接时, dvt_1_form_insertmode 被设为1,我们可以以此进行判断。

  




<xsl:when test="$dvt_IsEmpty">


  
…改为…
  
  
  




<xsl:when test="$dvt_IsEmpty and not($dvt_1_form_insertmode = '1')">

  
  现在,我们该如何显示insert 链接呢?
  选择 1. 因为 empty 模版被调用,我们可以简单的把insert 链接同时添加到该模版中。在与Richard的 STP discussion 中, Matt Bramer 建议将该链接添加到dvt_ViewEmptyText下面。




<xsl:template name="dvt_1.empty">
   <xsl:variable name="dvt_ViewEmptyText">There are no items to show in this view.</xsl:variable>
   <table border="0" width="100%">
      <tr>
         <td class="ms-vb">
            <xsl:value-of select="$dvt_ViewEmptyText" />
         </td>
      </tr>
      <tr>
         <td class="ms-vb">
            <a href="javascript: {ddwrt:GenFireServerEvent('__cancel;dvt_1_form_insertmode={1}')}">insert</a>
         </td>
      </tr>
   </table>
</xsl:template>

DSC0004.png


选择 1: 在空列表信息下添加insert 链接  选择 2. 与其放在单独一行里,倒不如直接跟在dvt_ViewEmptyText后面。



<xsl:template name="dvt_1.empty">
   <xsl:variable name="dvt_ViewEmptyText">There are no items to show in this view.</xsl:variable>
   <table border="0" width="100%">
      <tr>
         <td class="ms-vb"><xsl:value-of select="$dvt_ViewEmptyText" /> Be the first to <a href="javascript: {ddwrt:GenFireServerEvent('__cancel;dvt_1_form_insertmode={1}')}">insert a list item</a>.
         </td>
      </tr>
   </table>
</xsl:template>

  
DSC0005.png


选项 2: 把insert 链接放在空列表信息后
  选项 3. 另一种使得insert 模版被调用的方法是将其从xsl:choose 块中移出来,使其必然运行。
  



<xsl:choose>
    <xsl:when test="$dvt_IsEmpty and not($dvt_1_form_insertmode = '1')">
        <xsl:call-template name="dvt_1.empty" />
    </xsl:when>
    <xsl:otherwise><table border="0" width="100%" cellpadding="2" cellspacing="0">
        <tr valign="top">
            <xsl:if test="$dvt_1_automode = '1'" ddwrt:cf_ignore="1">
                <th class="ms-vh" width="1%" nowrap=""></th>
            </xsl:if>
            <th class="ms-vh" nowrap="">Your Field</th>
            .
            .
        </tr>
        <xsl:if test="not($dvt_1_form_insertmode = '1')"><xsl:call-template name="dvt_1.body">
            <xsl:with-param name="Rows" select="$Rows"/>
            <xsl:with-param name="FirstRow" select="1" />
            <xsl:with-param name="LastRow" select="$LastRow - $FirstRow + 1" />
        </xsl:call-template></xsl:if>
        <xsl:call-template name="dvt_1.rowinsert">
            <xsl:with-param name="IsInsertMode">
                <xsl:if test="$dvt_1_form_insertmode = '1'">1</xsl:if>
            </xsl:with-param>
        </xsl:call-template>
    </table>
    <xsl:call-template name="dvt_1.commandfooter">
            .
            .
    </xsl:call-template></xsl:otherwise>
</xsl:choose>

  …变成…



<xsl:choose>
    <xsl:when test="$dvt_IsEmpty and not($dvt_1_form_insertmode = '1')">
        <xsl:call-template name="dvt_1.empty" />
    </xsl:when>
    <xsl:otherwise><table border="0" width="100%" cellpadding="2" cellspacing="0">
        <tr valign="top">
            <xsl:if test="$dvt_1_automode = '1'" ddwrt:cf_ignore="1">
                <th class="ms-vh" width="1%" nowrap=""></th>
            </xsl:if>
            <th class="ms-vh" nowrap="">Your Field</th>
            .
            .
        </tr>
        <xsl:if test="not($dvt_1_form_insertmode = '1')"><xsl:call-template name="dvt_1.body">
            <xsl:with-param name="Rows" select="$Rows"/>
            <xsl:with-param name="FirstRow" select="1" />
            <xsl:with-param name="LastRow" select="$LastRow - $FirstRow + 1" />
        </xsl:call-template></xsl:if>
    </table>
    <xsl:call-template name="dvt_1.commandfooter">
            .
            .
    </xsl:call-template></xsl:otherwise>
</xsl:choose>
<table border="0" width="100%" cellpadding="2" cellspacing="0">
    <xsl:call-template name="dvt_1.rowinsert">
        <xsl:with-param name="IsInsertMode">
            <xsl:if test="$dvt_1_form_insertmode = '1'">1</xsl:if>
        </xsl:with-param>
    </xsl:call-template>
</table>

  注意其中第一段代码中的第 19-23行被移到了xsl:otherwise 块的外面(对应到第二段代码中的第26-30 行)。但它们还是被包裹到table标记中,因为这些标记是包含在xsl:otherwise 中的, dvt_1.rowinsert 模版中并没有这些标记。




DSC0006.png

选项 3: 把模版调用移到xsl:otherwise 块外面
  选项 4. 就个人而言,我喜欢显示列标题,即使该列表是空的。因此,与上面几个选项类似,我们也可以把标题行从xsl:choose 中分离出来,这样他们就会出现在每一个场景中。 (我喜欢第2种方案,所以下面的代码假设你是在empty模版中处理insert 链接的输出。)



<xsl:choose>
    <xsl:when test="$dvt_IsEmpty and not($dvt_1_form_insertmode = '1')">
        <xsl:call-template name="dvt_1.empty" />
    </xsl:when>
    <xsl:otherwise><table border="0" width="100%" cellpadding="2" cellspacing="0">
        <tr valign="top">
            <xsl:if test="$dvt_1_automode = '1'" ddwrt:cf_ignore="1">
                <th class="ms-vh" width="1%" nowrap=""></th>
            </xsl:if>
            <th class="ms-vh" nowrap="">Your Field</th>
            .
            .
        </tr>
        <xsl:if test="not($dvt_1_form_insertmode = '1')"><xsl:call-template name="dvt_1.body">
            <xsl:with-param name="Rows" select="$Rows"/>
            <xsl:with-param name="FirstRow" select="1" />
            <xsl:with-param name="LastRow" select="$LastRow - $FirstRow + 1" />
        </xsl:call-template></xsl:if>
        <xsl:call-template name="dvt_1.rowinsert">
            <xsl:with-param name="IsInsertMode">
                <xsl:if test="$dvt_1_form_insertmode = '1'">1</xsl:if>
            </xsl:with-param>
        </xsl:call-template>
    </table>
    <xsl:call-template name="dvt_1.commandfooter">
            .
            .
    </xsl:call-template></xsl:otherwise>
</xsl:choose>

  …改为…



<table border="0" width="100%" cellpadding="2" cellspacing="0">
    <tr valign="top">
        <xsl:if test="$dvt_1_automode = '1'" ddwrt:cf_ignore="1">
            <th class="ms-vh" width="1%" nowrap=""></th>
        </xsl:if>
        <th class="ms-vh" nowrap="">Your Field</th>
        .
        .
    </tr>
    <xsl:choose>
        <xsl:when test="$dvt_IsEmpty and not($dvt_1_form_insertmode = '1')">
            <xsl:call-template name="dvt_1.empty" />
        </xsl:when>
        <xsl:otherwise>
            <xsl:if test="not($dvt_1_form_insertmode = '1')"><xsl:call-template name="dvt_1.body">
                <xsl:with-param name="Rows" select="$Rows"/>
                <xsl:with-param name="FirstRow" select="1" />
                <xsl:with-param name="LastRow" select="$LastRow - $FirstRow + 1" />
        </xsl:call-template></xsl:if>
        <xsl:call-template name="dvt_1.rowinsert">
            <xsl:with-param name="IsInsertMode">
                <xsl:if test="$dvt_1_form_insertmode = '1'">1</xsl:if>
            </xsl:with-param>
        </xsl:call-template>
        <xsl:call-template name="dvt_1.commandfooter">
                .
                .
        </xsl:call-template></xsl:otherwise>
    </xsl:choose>
</table>

  
  注意,table标记并没有包含所有xsl:choose中的内容。所以我们需要快速的串一遍整个模版的调用过程,以保证其运转过程和我们预想的一致。
  



  • dvt_1.empty 并没有在 table 里,但现在却包进来了。所以要移除其table 标记,以使得其中的tr落入主table中。





<xsl:template name="dvt_1.empty">
    <xsl:variable name="dvt_ViewEmptyText">There are no items to show in this view.</xsl:variable>
    <table border="0" width="100%">
        <tr>
            <td class="ms-vb"><xsl:value-of select="$dvt_ViewEmptyText" /> Be the first to <a href="javascript: {ddwrt:GenFireServerEvent('__cancel;dvt_1_form_insertmode={1}')}">insert a list item</a>.            </td>
        </tr>
    </table>
</xsl:template>


…变成…




<xsl:template name="dvt_1.empty">
    <xsl:variable name="dvt_ViewEmptyText">There are no items to show in this view.</xsl:variable>
    <tr>
        <td class="ms-vb" colspan="99"><xsl:value-of select="$dvt_ViewEmptyText" /> Be the first to <a href="javascript: {ddwrt:GenFireServerEvent('__cancel;dvt_1_form_insertmode={1}')}">insert a list item</a>.        </td>
    </tr>
</xsl:template>


我们需要添加 colspan="99" 到 td 上,以确保其横跨整个由列头创建的table。


dvt_1.commandfooter 同样也是在table外,但现在被包进来了。所以也要做同样的修改。



<xsl:template name="dvt_1.commandfooter">
    <xsl:param name="FirstRow" />
    <xsl:param name="LastRow" />
    .
    .
    <table cellspacing="0" cellpadding="4" border="0" width="100%">
        <tr>
            <xsl:if test="$ShowFormActions = '1'">
                <xsl:call-template name="dvt_1.formactions" />
            </xsl:if>
            .
            .        </tr>
    </table>
</xsl:template>

…改为…



<xsl:template name="dvt_1.commandfooter">
    <xsl:param name="FirstRow" />
    <xsl:param name="LastRow" />
    .
    .
    <tr>
        <xsl:if test="$ShowFormActions = '1'">
            <xsl:call-template name="dvt_1.formactions" />
        </xsl:if>
        .
        .    </tr>
</xsl:template>

DSC0007.png




    选项 4: 包含列头(也是用的选项2的方法输出的insert链接)
    至此,我们通过少许更改,修正了SharePoint默认的功能,使得在空列表的情况下可以显示插入链接。





参考资料
SharePoint:Extending the DVWP - Bonus:Fixing the Insert Form Action When "No Mathcing Items"
  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-120174-1-1.html 上篇帖子: 转摘:更改SharePoint 的web.config设置的两种方式 下篇帖子: SharePoint 2013版本表
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表