RSS

Monthly Archives: 二月 2011

SharePoint 2010中自定义字段的变化

自定义字段类型在SharePoint 2007的时代出现,一举弥补了很多应用中的不足,很久之前也写过一篇关于用自定义字段类型拼装应用的Blog:《将SharePoint提升为应用开发平台》(之前Blog上的图都没了,某天突然有人告诉我说这篇文章被放到MSDN上了,汗……)

在SharePoint 2010中,自定义字段类型的开发大致没什么变化(我还没有测试过那个非常恶心的自定义字段类型的自定义属性的自定义设置画面的保存问题,在2010里面有没有得到改善,有时间试一下……)。但是在处理显示的时候,和2007相比有了很大的变化。

众所周知,2010中列表视图的默认WebPart已经从LVWP(ListViewWebPart)换成了XsltListViewWebPart,因此在默认情况下所有字段在视图中的显示,都是通过XSLT来渲染的。因此,当我们把一个2007里面写好的自定义字段类型部署到2010上的时候,会发现在fldtypes_***.xml中写的那些DisplayPattern和HeaderPattern都不生效了。

这里面有两个处理方法:

方法一:让CAML渲染重新生效,只需要在那个xml文件中加入如下一行就行:

   1: <Field Name="CAMLRendering">TRUE</Field>

方法二:使用新的xslt渲染机制。

在14\TEMPLATES\LAYOUTS\XSL目录中,创建一个fldtypes_***.xsl文件,将字段的视图渲染放进去(SharePoint默认的那些字段渲染样式就是该目录中的FLDTYPES.xsl文件,可以作为编写时的参考),建立形如下面的这种内容:

   1: <?xml version="1.0" encoding="utf-8"?>
   2: <xsl:stylesheet xmlns:x="http://www.w3.org/2001/XMLSchema"
   3:                 xmlns:d="http://schemas.microsoft.com/sharepoint/dsp"
   4:                 version="1.0"
   5:                 exclude-result-prefixes="xsl msxsl ddwrt"
   6:                 xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime"
   7:                 xmlns:asp="http://schemas.microsoft.com/ASPNET/20"
   8:                 xmlns:__designer="http://schemas.microsoft.com/WebParts/v2/DataView/designer"
   9:                 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  10:                 xmlns:msxsl="urn:schemas-microsoft-com:xslt"
  11:                 xmlns:SharePoint="Microsoft.SharePoint.WebControls"
  12:                 xmlns:ddwrt2="urn:frontpage:internal">
  13:   <xsl:template match="FieldRef[@FieldType='CustomField']" mode="Note_body">
  14:     <xsl:param name="thisNode" select="." />
  15:     <xsl:value-of select="$thisNode/@*[name()=current()/@Name]"
  16:                   disable-output-escaping="yes" />
  17:   </xsl:template>
  18: </xsl:stylesheet>
  19:  
  20:  

SharePoint是通过其中的下面这一行来匹配字段的:

   1: <xsl:template match="FieldRef[@FieldType='CustomField']" mode="Note_body">

match属性决定了字段的匹配规则,上图中是使用FieldType,也就是字段类型来进行匹配,这个值和在fldtypes_***.xml中定义的TypeName的值是要保持一致的。除此之外,这里也可以使用字段名称来进行匹配,例如:

   1: <xsl:template match="FieldRef[@Name='MyField']" mode="Note_body">

来匹配所有内部名称为“MyField”的那些字段,后面的mode是字段显示的基础样式类型,可以参考FLDTYPES.xsl中的内容。

在SharePoint 2007中,DisplayPattern除了能够控制视图的显示样式之外,还可以控制在字段查看状态下(比如列表条目查看页面DispForm.aspx)中的样式。但是到了2010里面,不论是DisplayPattern还是xslt,都只能够控制视图中的显示样式,而控件查看状态下的样式,必须通过字段的控件来进行定义——这样也造成了2007的时候,控件和CAML都可以定义查看样式的冲突。

BTW,其实我不太会写xslt,本来想用CAML就完了,结果发现在继承多行文本(SPFieldMultiLineText)的时候,html死活显示不出来,一直都被编码,google许久没找到原因,最后只好上了xslt的贼船,有时间需要系统的学一下xslt了……

一些参考文章:

1、How to: Customize the Rendering of a Field on a List View

2、RenderPattern Element (Field Types)

3、Custom field type list view rendering in XSLT (一个例子)

 

Posted by on 2011 年 02 月 22 日 in SharePoint

Leave a comment

Tags:

SharePoint程序中的多语言支持

前些天 kaneboy 在博客中写了一篇关于SharePoint UI多语言支持的博客:《SharePoint 2010多语言UI,以及开发人员需要注意的》,本篇内容是对这篇Blog的一些补充和完善。

涂总的blog中主要是在介绍关于列表名称、字段名称等这些内容的多语言设置,在用程序创建一个列表/字段的时候,为了能够支持多语言,应该使用XXXResource属性来代替XXX属性(例如TitleResource代替Title)。实际上,如果我们是在网站中直接创建的这个列表/字段,例如在中文网站中(默认语言),创建了一个叫“QQ号码”的字段;而当我们切换到另一种语言的时候(比如英文),我们直接对这个字段改名为“QQ Number”,这个时候并不会覆盖中文语言的名称,而是只改变当前语言下的字段名称设置。通过这种方式,我们也可以在不同的语言环境中对同一个字段使用不同的名称。

需要注意的是,如果我们在网站设置 – 语言设置中,将“覆盖翻译”设置为“是”的时候,一旦我们在默认语言的网站中更改了字段名称,那么会覆盖掉其他语言网站的名称设置,我们需要重新切换语言,再进行一次设置。见下图:

image

下面介绍一些SharePoint中和多语言编程相关的对象模型

1、如何获取不同语言下,网站中一些默认文本?

通过使用SPResouce的静态方法GetString,该方法有两种重载:

   1: public static string GetString(string name, params Object[] values);
   2: public static string GetString(CultureInfo culture, string name, params Object[] values);

第一种方法是获取当前语言下指定的字符串,第二种是获取指定语言下指定的字符串(通过第一个参数)。

第二个参数就是资源字符串的名称,例如“LanguageNameInLocalizedLanguage”就是使用的语言,如果环境是简体中文,取到的就是“中文 – 简体”,如果环境是英文,取到的就是“English”。

第三个参数是使用的值,如果第二个参数中的字符串包含诸如{0}、{1}这样的占位符,则在第三个参数中指定这些占位符的具体值。

2、如何知道服务器上安装了哪些语言包?

有两种方法可以取得:

   1: spRegionalSettings.InstalledLanguages;
   2: SPRegionalSettings.GlobalInstalledLanguages;

第一种方法要先获取一个SPRegionalSettings对象,可以通过spWeb的RegionalSettings属性获取或者直接使用SPContext.Current.RegionalSettings;第二种方法是SPRegionalSettings的一个静态属性。

两种方法返回的都是SPLanguageCollection类型的对象,在SPLanguage中包含了LCID属性和DisplayName属性可以分别取得语言的lcid和显示名称(经测试,这个显示名称好像就是在默认语言下的显示名称,不会跟着当前环境语言而改变)

3、如何知道当前网站可以使用哪些语言?

在网站设置 – 语言设置中,可以选择当前网站中可以使用的语言,包括默认语言,以及备用语言(如果这边不选中对应的备用语言的话,即使安装了语言包,在网站中也用不了这个语言)。

通过使用spWeb的SupportedUICultures属性,可以获取到当前网站可以使用的语言,这个属性是一个IEnumerable<CultureInfo>类型的对象。需要注意的是,这个属性在沙盒解决方案中是不可用的。

4、如何得知网站的默认语言?

在后台程序中,可以通过spWeb的Language属性(int类型),获取默认语言的lcid。

在前台JavaScript程序中,可以通过_spPageContextInfo.webLanguage来获取这个lcid。

5、如何得知当前网站上正在使用哪种语言?

在后台程序中,可以通过Thread.CurrentThread.CurrentUICulture来获取当前环境的语言地区设置。

在前台JavaScript程序中,可以通过变量g_wsaLCID或者_spPageContextInfo.currentLanguage获取到当前语言的lcid。

 

那么,SharePoint网站支持多语言有哪些方式呢?

一种方式就是从2007沿用下来的,使用变体的方式(仅在server版中才有),这种方式是为每个语言创建一个独立的网站。

另一种方式,就是2010新增的,在同一个网站中对多语言的支持(也是上文反复说明的)。在这种方式下,网站的标题、描述信息,列表的标题、描述信息,字段的标题、描述信息,导航结点,托管元数据都是有多语言支持的。如果想要让一个普通的列表字段内容也支持多语言(在不同语言环境中显示不同的值),那就需要开发自定义字段类型了(2010中,只有托管元数据字段类型是包含多语言支持的),下图是一个开发好的一个多语言单行文本的效果:

编辑画面:

image

中文下的显示画面:

image

英文下的显示画面:

image

 

Posted by on 2011 年 02 月 22 日 in SharePoint

Leave a comment

Tags:

SharePoint中详细的版本对比

众所周知,在SharePoint 2007的时候,列表和文档库都支持了版本控制,并且在版本控制中,可以看到哪些字段发生了变化,如下图所示:

image

不过在最近,某个项目中,客户说:这个版本历史记录没啥用啊(做的是公文管理模块),我得知道我发的好长好长一段的公文(用的一个多行文本实现的),到底是什么地方变了,得用个红字给我标出来。然后我们乙方在场的人就无语了。

这种对比两个文本字符串区别的功能,有个正式的名字叫做“字符串编辑距离(Edit Distance)”,通俗一点说就是怎么从一个字符串,通过增加、变更、删除的动作,变成另一个字符串的。这是动态规划算法的一个典型应用,不过要自己来写(而且客户的这个发文还是html格式的),恐怕不是一朝一夕能搞得定的。

其实SharePoint中,这种详细的版本内容比较确实是有的,那就是在wiki页面库中,版本历史记录可以记录下两个不同版本的正文有什么区别,不过只支持wiki库的正文字段,效果是这个样子的:

image

通过跟踪源代码,发现其实在SharePoint中,这种版本对比功能已经在API中提供了接口,那就是SPDiffUtility(在Microsoft.SharePoint.Utilities命名空间中)的静态方法Diff。这个方法有三个参数,前两个参数是需要对比的两个字符串,第三个参数指定最多返回多少个差异的地方(一个int),方法返回字符串的差异结果,是一段html,样子就像是上面那张图的样子。

有了这个方法再实现起来就相对容易很多了,不过这个方法有如下两个大问题:

  1. 这个方法只支持对比html格式的字符串,对于纯文本字符串,在返回的时候,也是html格式,但是换行就无法以“换行”的形式显示出来了。
  2. 通过对这个方法进行反编译可以看到,这个方法在进行两个字符串对比的时候,是按照空格作为两个单词的分隔符(这个分隔算法是用一个整则表达式,\s+写死在代码里的),所以我们看到在中文的情况下,就会出现上图那样的状况,即使变动的只是一个字,但是系统也认为是整个段落的变动。
  3. 在SharePoint这个方法的实现中,只有“新增”和“删除”两种动作,变更的动作是通过“删除”+“新增”的方式来表示的,相对来说比较不直观。

 

第一个问题,其实解决起来很简单,把纯文本转换成html就行了,做一个HtmlEncode,然后把换行符替换为“<br/>”就行了。

第二个问题,其实说起来也很简单,在我们最终的实现方式中,是以“短句”为单位进行的对比,方法就是先对待比较的字符串进行一下处理,把几个句尾标点替换成包含空格的标记,比较完之后再替换回来:

   1: private string ChangeString(string str)
   2: {
   3:     if (str == null)
   4:        return "";
   5:     return str.Replace("。", "。`` ").Replace("!", "!`` ").Replace("?", "?`` ").Replace("、", "、`` ")
   6:         .Replace(",", ",`` ").Replace(":", ":`` ").Replace(";", ";`` ");
   7: }

比较完之后,删除里面所有的““ ”就可以了(这个序列在正常的文本中基本上不会出现),这样再调用方法的时候,替换后的部分就包含空格,可以被SharePoint识别为对比的分隔符了。

至于第三个问题,基本上没有很好的办法,不过一般客户都能够接受。

重新仿照SharePoint的方式写了一个新的页面,传入待对比的列表的ID、条目的ID和字段的名称,修改之后的结果如下图:

image

可以看到,这要比之前的那个效果好很多了。

如果希望重新定义“已删除”和“已添加”的样式,也很容易,这是两个css(ms-diffdelete和ms-diffinsert),直接修改样式表就行了。

 

Posted by on 2011 年 02 月 04 日 in SharePoint

Leave a comment

Tags: