2009年1月31日,星期六

扩展Web部件框架-第1部分

今天,我想向我们的一位客户展示我们使用Web部件所做的一些有趣的事情。有很多要讨论的内容,因此将涉及两篇文章:

  • 第1部分-背景和实现
  • 第2部分-问题和解决方案

我认为有些事情特别酷,因为我们已经有效地将经典的WCM(发布)站点功能与Web部件框架的自定义实现相结合。对于企业客户来说,上下文是相当大的部署,但是我们要部署的是一个80-100的集中式平台 互联网 网站。我们的想法是,在80-100个国家/地区中,内容创作团队将利用我们在MOSS上提供的内容来创建自己的网站-用不一致的品牌/外观替换现有的使用不同技术的网站。

显然,这里的主要挑战是满足众多利益相关者的多样化需求。因此,该平台的基石是可以对网站进行一定程度的定制,因此每个国家/地区都有一定的灵活性,可以以他们认为最好的方式与受众进行交流。我们有效地为作者提供了一组页面模板和构建块,以及一个系统,该系统管理这些块如何组合在一起,以便用户体验仍然“有意义”。不用说,已经进行了很多分析和考虑-无论是需要什么功能,还是整个站点的用户旅程和导航,而我们这边的经验架构师(LBi)都在这里起着至关重要的作用。我可以在这个项目中涉及很多方面,但是由于我想在这里关注实现细节,因此我将 短暂地 在展示我们如何做到之前,列出其中一些构建基块要求。

关键要求/挑战:

为了创建不同的页面类型,我们需要大约15个 页面布局,其中包括:

  • 主页
  • 频道集线器/备用集线器/子主页-这些是“第二层和第三层”页面的不同模板选项 
  • 内容页
  • 产品页面
  • 媒体发布
  • 列表-提供指向一系列相关页面的链接
  • 等等。

虽然页面功能的某些方面已“固定”在模板上,但还有许多其他项目是可选的-这些项目将由作者以“ Web部件”方式或其他方式添加到页面中。这些可选的一些例子 “页面模块” 分别是:

  • “英雄”功能-用于通过图片/ Flash /文字突出显示突出页面上的内容
  • 右手促销
  • 内容编辑器模块-允许作者输入任意内容,但出于显而易见的原因,我们开发了一个有趣的自定义控件,该控件有点像发布HtmlField和内容编辑器Web部件之间的交叉(稍后介绍)
  • 通用内容模块-汇总格式化的内容/链接到所选页面
  • 列表/选项卡式列表-提供指向一系列相关页面的链接
  • 动态股价-根据网络服务调用显示最新股价
  • 产品选择器-使用AJAX级联下拉列表过滤产品
  • 等等。

尽管还有很多其他挑战(例如 多语言内容,打包/记录每个部署方面的内容,以便托管公司可以部署等!),我觉得构建“框架”可能比单独的功能更具挑战性。为了帮助您构筑接下来要阅读的内容,请先写一些 问题 我们用于实施的是:

  • 这些可选功能如何添加到页面中?作为Web部件,还是其他?
  • 如果是Web部件,我们如何获得可访问性?
  • 如果没有Web部件,我们如何提供配置?
  • 我们如何限制哪些模块可以在哪里使用(根据规范)?
  • 由于我们位于“灵活的”发布站点中,我们如何确定内容类型上需要哪些字段?每个内容类型是否都需要具有作者可能选择添加的所有可能字段?
  • 如果我们正在使用发布控件,我们如何将动态添加的控件绑定到内容类型上的“后端”发布字段?

实施

除可选的页面模块外,大多数模板都有一组经典的发布字段。在研究了自定义方法之后,我们得出结论,Web部件框架在可选内容上有很多用处-显然,我们可以避免构建用户界面来从列表/添加到页面/允许配置特定于属性的模块中选择模块。模块,以及拖放(以及其他功能)作为额外的奖励。 Web部件的概念 区域- 作为可以放置一个或多个模块的容器-对我们的页面结构也很重要。

可选模块的另一个挑战是数据的存储位置。如果他们要发布字段,我们将需要每个可能的模块在每个可能的内容类型上都有一个相应的字段,而在查看规范时这是不切实际的。 Web部件当然使用不同的模型,并且该框架负责数据存储,而不管页面上有多少控件。

不利的一面是,在发布页面中使用Web部件要记住的关键一件事是(根据定义)Web部件数据未存储在发布字段中,因此不会以相同的方式进行版本控制。在与客户讨论之后,在我们的案例中,由于将内容存储在发布字段中与将Web部件存储在内容中是分开的,因此,这对我们的影响没有我们最初想象的那么大。因此,在客户接受这一权衡取舍之后,我们使用了Web部件并提出了以下解决方案元素:

  1. 模块矩阵

    这包括两个SharePoint列表,其中包含“规则矩阵”,以加强设计团队对在哪种页面类型上可以使用哪些功能的规范。有效地,数据提供了模块和页面布局的映射。作为清单数据,这意味着如果需要更改策略,中央团队可以轻松地对其进行更新。我们的基础Web部件(第4点)消耗了这些数据。

  2. 类似于SmartPart的方法,但具有Web部件属性

    我们希望在用户控件中实现Web部件的实际功能,这是避免在C#代码中构建HTML的典型原因(在很多级别上都是错误的!)。显然,这是SmartPart使用LoadControl()所做的事情,但是我们还有其他要求,需要将Web部件属性值传递给我们的用户控件-这意味着我们可以使用熟悉的“工具部件”界面(即在右侧窗格)进行控件配置。 

    在我们的模型中,每个用户控件都有一个对应的“包装” Web部件/工具部件,该部件了解哪些属性是必需的以及如何构建属性UI。在Web部件的OnInit()方法中,将值从Web部件属性传递给用户控件,以便对用户控件进行初始化以准备进行处理。

  3. 基础Web部件/基础工具部件

    我们所有的Web部件/工具部件均来自我们的自定义类,该类抽象了一些职责。由于我们无法轻松地将Web部件选择器屏幕更改为仅显示作者所选区域的适当Web部件,因此我们将检查内置到基本Web部件中-如果添加了“无效” Web部件,则该Web部件将呈现在演示模式下什么都没有,但是在编辑模式下,我们向作者显示一条消息是这样的:

    ModuleNotValidMessage 

    新增中 太多 到区域的Web部件(在模块矩阵数据中确定的数量)将具有类似的效果。

  4. 将发布字段控件的界面与Web部件存储相结合

    决定将Web部件用于我们的控制体系结构后,我们对与标准内容编辑器Web部件(CEWP)类似的内容有一个要求。但是,与MOSS发布的HtmlField相比,此控件非常la脚,而且我们迅速建立了比基本CEWP还要更多的客户端。因此,我们结合了我们想要的两者-发布字段类型使用的前端控件(RichHtmlField控件),但保留了Web部件存储的后备存储,而不是发布字段。这意味着作者可以在其页面上添加此可选模块的多个实例(并获得良好的编辑体验),但是由于它是Web部件,因此我们无需担心每种可能的内容类型上都有对应的字段集。在代码/集成方面,这是相同的方法,但是最后,我们实际上将标准MOSS控件替换为Telerik的RADEditor字段前面的控件,因为客户端希望移至此: 

    CustomContentEditorWebPart  

    还要注意,这里通常使用另一个用于发布字段的控件AssetUrlSelector-这提供了上面显示的“浏览...”按钮,可用于为作者提供浏览文件的友好方式。

  5. WebPartZone的控制适配器,以实现可访问性

    由于Web部件通常使用一堆嵌套的HTML表进行呈现,而这些嵌套的HTML表无法针对AA进行验证,因此,如果可访问性是设计目标,则需要采取措施对此进行补救。但是,这不一定有什么大不了的-方法是您为WebPartZone控件“纠正” HTML 仅在演示模式下, 因此,对于所有需要发生的所有Web部件编辑框架来说,这些表都处于编辑模式下。您确实失去了客户端 Web部件服务组件(WPSC) API可以这样做,但是无论如何我们都没有要求(我很少看到它使用过)。我最初以为我必须写一个控制适配器来做到这一点,但是我发现 大卫·施耐德(David Schneider)已经完成工作 -很好。也可能是最新版本的 AKS 有一个,不记得我是否检查过。

  6. 仅呈现 我们的 Web部件选择器中的Web部件

    由于这是一个高度定制的WCM平台,而不是标准的协作环境,因此我们不希望在选择器中看到这些网站的任何标准Web部件。此步骤分两个步骤:

    -从网站的Web部件库中删除所有.webpart文件(注意,我们使用Kivati在所有网站集中推出了此类更改-以后将对此进行更多介绍)。但是,这样做仍将使您拥有站点中所有列表/库的ListView Web部件,因此您也需要这样做。
    -确保您所有的WebPartZone声明都将记录很少的'QuickAdd-ShowListsAndLibraries'属性设置为false:
    <WebPartPages:WebPartZone id="g_AB07678E486C46bc962DFC8446A6CD13" runat="server" title="Zone 1" QuickAdd-ShowListsAndLibraries="false" />


    这样,对于任何不适合我们的情况的标准Web部件,作者都不会感到困惑:

    StrippedWebPartPicker


  7. 编辑Web部件属性(工具部件)时删除不必要的选项

    最后,我们对Web部件的随附工具部件(用于属性编辑)做了一些工作,以避免使我们的作者混淆那些不会生效的选项。例如,对于在演示模式下看起来像这样的Web部件:

    产品选择器模块 

  8. 工具部分如下所示:

    ProductSelectorToolPart

    如果您想知道要看的是什么,那是因为我们希望控制它们以确保正确的格式,因此我们删除了SharePoint通常为每个Web部件提供的标准选项(例如chrome样式等)。通常,我们将在工具部分的底部包含以下部分:

    RemovedToolPartOptions

概要

的SharePoint的Web部件框架可以通过多种方式进行扩展,这里我仅展示了我们遵循的路径。对于我们客户这样的需求,Web部件提供了一个很好的起点,也许表明,只要能够理解和接受这些折衷,有时在可访问的发布站点中就有Web部件的位置。

在本系列的第2部分中,我们将研究遇到的问题及其解决方案。

6条评论:

匿名 said...

克里斯你好
最终该网站的可访问性如何?
是否符合XHTML和“ AA”标准?

保持职位。

奈杰尔

Mads Nissen(Puzzlepart.com)说过...

1.出色的工作。这是将Webpart的“用户选项”和“管理选项”分开的一个好步骤。
2.可能是一个愚蠢的问题:您使用了哪种隐式方法从工具窗格中删除外观等内容?

克里斯·奥'Brien说过...

感谢Mads。

重新阅读这篇文章,令我震惊,我确实对我们如何做到这一点保持沉默,认为该段从结尾处溜了下来;-)

简而言之,可以通过重写GetToolParts()方法(该方法返回一组工具部件)并确保您的自定义工具部件是其中唯一的方法来完成此操作。默认情况下,SharePoint将成为此集合的默认工具。

干杯,

克里斯。

克里斯·奥'Brien说过...

嗨,奈杰尔,

抱歉,仅注意到此评论。那是XHTML,我们 主要是 AA,但在几个地方都是A。客户的目标是A,但实际上对他们来说并不是一个重中之重。

干杯,

克里斯。

未知说过...

您是否在客户处实施了该项目?如果是,那么实施是否接近企业所提出的要求?

您是否打算撰写本文的第二部分?

克里斯·奥'Brien说过...

@Masti Masti,

是的,完成的项目确实非常接近原始客户的需求。

可以在以下位置找到本文的第2部分 http://www.milwaukeeticketsblog.com/2009/02/extending-web-part-framework-part-2.html.

HTH,

克里斯。