演练:创建移动适配器
上次修改时间: 2011年4月1日
适用范围: SharePoint Foundation 2010
本演练演示了如何为 Microsoft SharePoint Foundation 附带的 UserTasksWebPart 创建移动适配器。有关创建移动 Web 部件适配器的过程的更高级别讨论,请参阅如何创建移动适配器。
先决条件
回顾主题SharePoint Foundation 开发工具及其子主题,并执行推荐的用于设置开发环境的任务。特别需要指出,本演练假定您已执行设置移动设备仿真器、如何:创建用于获取程序集公钥的工具和如何:向 PATH 环境变量中添加工具位置中推荐的任务。
开发适配器
以下步骤介绍了创建移动适配器的过程。
设置移动适配器项目
在 Visual Studio 中,选择"文件"菜单上的"新建",然后选择"项目"。
在"新建项目"对话框中,选择"项目类型"框中的"Visual C#",选择"模板"框中的"类库",然后在"名称"框中输入 MobileAdapters。单击"确定"。
右键单击"解决方案资源管理器"中的"引用"节点,单击"添加引用",然后在按住 Ctrl 键的同时,选择"添加引用"对话框中".NET"选项卡上的"System.Web"、"System.Web.Mobile"和"Microsoft.SharePoint"。单击"确定"。
右键单击"解决方案资源管理器"中的项目名称并选择"属性"。
在"属性"对话框的"应用程序"选项卡上,输入 MyCompany.SharePoint.WebPartPages.MobileAdapters 作为"程序集名称",输入 MyCompany.SharePoint.WebPartPages 作为"默认命名空间"。用您的公司名称替换 MyCompany。将本演练中的所有 MyCompany 都替换为您的公司名称。
单击"程序集信息"并根据需要在"程序集信息"对话框中进行更改。本演练假设您将程序集和文件版本保留为 1.0.0.0,并且您不更改 GUID。
打开"签名"选项卡,再选择"为程序集签名"。
从"选择强名称密钥文件"下拉列表框中选择"<新建...>"。
在"创建强名称密钥"对话框的"密钥文件名称"框中,键入 MobileAdapters.snk,然后确保未 选中"项目..."复选框。单击"确定"。
打开"生成事件"选项卡,并在"后期生成事件命令行"框中键入以下代码。该代码将运行您在稍后步骤中创建的批处理文件。
cd "$(ProjectDir)" MobileAdapterPostBuild
在工具栏上单击"保存所有文件"按钮。
在"解决方案资源管理器"中,将文件 Class1.cs 重命名为 UserTasksWebPartMobileAdapter.cs。
创建适配器控件
打开项目的 UserTasksWebPartMobileAdapter.cs 文件(如果此文件尚未打开),并添加以下 using 语句。
using System.Web.UI.MobileControls; using Microsoft.SharePoint; using Microsoft.SharePoint.WebPartPages; using Microsoft.SharePoint.Utilities;
Imports System.Web.UI.MobileControls Imports Microsoft.SharePoint Imports Microsoft.SharePoint.WebPartPages Imports Microsoft.SharePoint.Utilities
将命名空间更改为 MyCompany.SharePoint.WebPartPages.MobileAdapters。
用下面的代码替换整个 Class1 声明。
public class UserTasksWebPartMobileAdapter : WebPartMobileAdapter { }// end UserTasksWebPartMobileAdapter class
Public Class UserTasksWebPartMobileAdapter Inherits WebPartMobileAdapter End Class ' end UserTasksWebPartMobileAdapter class
请注意,您的新类将继承自 WebPartMobileAdapter。
添加重写 CreateControlsForDetailView() 方法的以下声明。
protected override void CreateControlsForDetailView() { } // end CreateControlsForDetailView
Protected Overrides Sub CreateControlsForDetailView() End Sub ' end CreateControlsForDetailView
使用以下行开始实现 CreateControlsForDetailView()。该代码在 Web 部件标题的左侧创建一个向下指的箭头。通过将 LinkToSummaryView 传递给帮助器方法 CreateWebPartIcon(WebPartMobileAdapter.WebPartIconLink),您可以使该箭头成为其浏览器支持 CSS 和 ECMAScript 1.0 或更高版本的设备上的切换开关。当用户单击该箭头时,Web 部件将折叠为其摘要视图。(如果浏览器不同时支持 CSS 和 ECMAScript 1.0 或更高版本,则会呈现不同的图标,单击该图标将打开包含 Web 部件摘要视图的页面。)
Image iconImage = this.CreateWebPartIcon(WebPartIconLink.LinkToSummaryView); iconImage.BreakAfter = false; this.Controls.Add(iconImage);
Dim iconImage As Image = Me.CreateWebPartIcon(WebPartIconLink.LinkToSummaryView) iconImage.BreakAfter = False Me.Controls.Add(iconImage)
添加以下行以呈现 User Tasks Web 部件的默认标题,即以粗体显示的"User Tasks"。
Label titleLabel = this.CreateWebPartLabel(); this.Controls.Add(titleLabel);
Dim titleLabel As Label = Me.CreateWebPartLabel() Me.Controls.Add(titleLabel)
添加以下行以收集对对象的引用,您的代码将在其呈现逻辑中引用这些对象。将 CustomSite 替换为您将从移动设备访问的网站的名称。它可以是包含标准 SharePoint Foundation 任务列表的任何网站。
SPSite siteCollection = SPContext.Current.Site; SPUser currentUser = SPContext.Current.Web.CurrentUser; SPList taskList = siteCollection.AllWebs["CustomSite"].Lists["Tasks"]; SPListItemCollection allTasks = taskList.GetItems(taskList.DefaultView);
Dim siteCollection As SPSite = SPContext.Current.Site Dim currentUser As SPUser = SPContext.Current.Web.CurrentUser Dim taskList As SPList = siteCollection.AllWebs("CustomSite").Lists("Tasks") Dim allTasks As SPListItemCollection = taskList.GetItems(taskList.DefaultView)
添加以下 LINQ 查询。where 子句可确保移动视图中只包含当前用户的任务。select 子句将投射一个只包含两个属性的新匿名类型。不需要适配器不打算呈现的字段。
备注
该代码使用 LINQ to Objects(该链接可能指向英文页面) 并筛选已位于内存中的数据(allTasks 对象)。若要实际阻止从内容数据库传输的不需要的列表项和字段,您需要使用 LINQ to SharePoint 提供程序。但是,若要演示该提供程序的用法,则会增加本演练的长度并且会偏离本演练的主题。
// Use LINQ to filter out other users ... var lightweightTasksOfUser = from SPListItem task in allTasks where task["AssignedTo"].ToString().EndsWith(currentUser.Name) select new {task.Title, Priority=task["Priority"]}; // ... and unneeded columns.
' Use LINQ to filter out other users ... Dim lightweightTasksOfUser = From task As SPListItem In allTasks Where task("AssignedTo").ToString().EndsWith(currentUser.Name) Select New With {Key task.Title, Key .Priority=task("Priority")} '... and unneeded columns.
添加 foreach 循环,该循环完成时,将会呈现当前用户任务列表中的每个项,最多限制为三项。
foreach (var lightweightTask in lightweightTasksOfUser) { } // end "for each lightweight task of the current user"
For Each lightweightTask In lightweightTasksOfUser Next lightweightTask ' end "for each lightweight task of the current user"
在该循环内,添加以下代码以呈现标准的 SharePoint Foundation 移动列表项项目符号。该代码使用对象初始值设定项语法,它需要 C# 3.0 来初始化属性。当然,您也可以使用单独的属性赋值语句。
Image taskIcon = new Image() { ImageUrl = this.ItemBulletIconUrl, BreakAfter = false}; this.Controls.Add(taskIcon);
Dim taskIcon As New Image() With {.ImageUrl = Me.ItemBulletIconUrl, .BreakAfter = False} Me.Controls.Add(taskIcon)
添加以下代码以呈现任务名称。请注意,Font() 是只读属性,它具有可写子属性,包括 Bold 和 Size。不能使用对象初始值设定项语法设置这些子属性。
Label taskTitle = new Label { Text = lightweightTask.Title, BreakAfter = false}; taskTitle.Font.Bold = BooleanOption.True; this.Controls.Add(taskTitle);
Dim taskTitle As Label = New Label With {.Text = lightweightTask.Title, .BreakAfter = False} taskTitle.Font.Bold = BooleanOption.True Me.Controls.Add(taskTitle)
添加以下代码以便任务标题后跟以小字体显示的任务优先级。请注意,此处提到的 Priority 属性是在由 LINQ 查询声明的匿名类型中临时 创建的。在 C# 中,您需要使用"task["Priority"]"引用该值,其中 task 是对"任务"列表中 SPListItem 对象的引用。
Label priority = new Label() { Text = " " + lightweightTask.Priority }; priority.Font.Size = FontSize.Small; this.Controls.Add(priority);
Dim priority As New Label() With {.Text = " " & lightweightTask.Priority} priority.Font.Size = FontSize.Small Me.Controls.Add(priority)
添加以下代码以便在每个任务后面放置一个空行。
this.Controls.Add(new LiteralText());
Me.Controls.Add(New LiteralText())
最后,添加以下 if 结构以便将呈现的任务数限制为三个,并在任务数超过三个时呈现一个指向用户的完整任务列表的链接。还请注意对象初始值设定项语法的使用。
// Render no more than 3 tasks, but provide link to others. if (itemCount++ >= 3) { Link moreItemLink = new Link { Text = "All my tasks", href = SPMobileUtility.GetViewUrl(taskList, taskList.Views["My Tasks"]) }; this.Controls.Add(moreItemLink); break; } // end "if limit has been reached"
' Render no more than 3 tasks, but provide link to others. If itemCount >= 3 Then itemCount += 1 Dim moreItemLink As Link = New Link With {.Text = "All my tasks", .href = SPMobileUtility.GetViewUrl(taskList, taskList.Views("My Tasks"))} Me.Controls.Add(moreItemLink) Exit For End If ' end "if limit has been reached" itemCount += 1
在 foreach 循环开头的正上方添加以下语句以初始化 itemCount 变量。
Int16 itemCount = 1;
Dim itemCount As Int16 = 1
整个声明现在应如以下代码示例所示。
protected override void CreateControlsForDetailView() { Image iconImage = this.CreateWebPartIcon(WebPartIconLink.LinkToSummaryView); iconImage.BreakAfter = false; this.Controls.Add(iconImage); Label titleLabel = this.CreateWebPartLabel(); this.Controls.Add(titleLabel); SPSite siteCollection = SPContext.Current.Site; SPUser currentUser = SPContext.Current.Web.CurrentUser; SPList taskList = siteCollection.AllWebs["MyGPSite"].Lists["Tasks"]; SPListItemCollection allTasks = taskList.GetItems(taskList.DefaultView); // Use LINQ to filter out other users ... var lightweightTasksOfUser = from SPListItem task in allTasks where task["AssignedTo"].ToString().EndsWith(currentUser.Name) select new {task.Title, Priority=task["Priority"]}; // ... and unneeded columns. Int16 itemCount = 1; foreach (var lightweightTask in lightweightTasksOfUser) { Image taskIcon = new Image() { ImageUrl = this.ItemBulletIconUrl, BreakAfter = false}; this.Controls.Add(taskIcon); Label taskTitle = new Label { Text = lightweightTask.Title, BreakAfter = false}; taskTitle.Font.Bold = BooleanOption.True; this.Controls.Add(taskTitle); Label priority = new Label() { Text = " " + lightweightTask.Priority }; priority.Font.Size = FontSize.Small; this.Controls.Add(priority); this.Controls.Add(new LiteralText()); // Render no more than 3 tasks, but provide link to others. if (itemCount++ >= 3) { Link moreItemLink = new Link { Text = "All my tasks", href = SPMobileUtility.GetViewUrl(taskList, taskList.Views["My Tasks"]) }; this.Controls.Add(moreItemLink); break; } // end "if limit has been reached" } // end "for each lightweight task of the current user" } // end CreateControlsForDetailView
Protected Overrides Sub CreateControlsForDetailView() Dim iconImage As Image = Me.CreateWebPartIcon(WebPartIconLink.LinkToSummaryView) iconImage.BreakAfter = False Me.Controls.Add(iconImage) Dim titleLabel As Label = Me.CreateWebPartLabel() Me.Controls.Add(titleLabel) Dim siteCollection As SPSite = SPContext.Current.Site Dim currentUser As SPUser = SPContext.Current.Web.CurrentUser Dim taskList As SPList = siteCollection.AllWebs("MyGPSite").Lists("Tasks") Dim allTasks As SPListItemCollection = taskList.GetItems(taskList.DefaultView) ' Use LINQ to filter out other users ... Dim lightweightTasksOfUser = From task As SPListItem In allTasks Where task("AssignedTo").ToString().EndsWith(currentUser.Name) Select New With {Key task.Title, Key .Priority = task("Priority")} '... and unneeded columns. Dim itemCount As Int16 = 1 For Each lightweightTask In lightweightTasksOfUser Dim taskIcon As New Image() With {.ImageUrl = Me.ItemBulletIconUrl, .BreakAfter = False} Me.Controls.Add(taskIcon) Dim taskTitle As Label = New Label With {.Text = lightweightTask.Title, .BreakAfter = False} taskTitle.Font.Bold = BooleanOption.True Me.Controls.Add(taskTitle) Dim priority As New Label() With {.Text = " " & lightweightTask.Priority} priority.Font.Size = FontSize.Small Me.Controls.Add(priority) Me.Controls.Add(New LiteralText()) ' Render no more than 3 tasks, but provide link to others. If itemCount >= 3 Then itemCount += 1 Dim moreItemLink As Link = New Link With {.Text = "All my tasks", .href = SPMobileUtility.GetViewUrl(taskList, taskList.Views("My Tasks"))} Me.Controls.Add(moreItemLink) Exit For End If ' end "if limit has been reached" itemCount += 1 Next lightweightTask ' end "for each lightweight task of the current user" End Sub ' end CreateControlsForDetailView
在"生成"菜单上选择"生成解决方案"。尽管此时您尚未完成操作,但需要编译程序集,这样才能够生成公钥标记。
在 compat.browser 文件中注册移动适配器
在文本编辑器或 Visual Studio 中打开文件 \\Inetpub\wwwroot\wss\VirtualDirectories\80\App_Browsers\compat.browser,并滚动到 refID 属性值为"default"的 <browser> 元素。(如果需要,请用目标 Web 应用程序的端口替换 URL 中的"80"。)
在 <controlAdapters> 元素内,添加以下内容作为子元素。
<adapter controlType="Microsoft.SharePoint.WebPartPages.UserTasksWebPart, Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" adapterType="MyCompany.SharePoint.WebPartPages.MobileAdapters.UserTasksWebPartMobileAdapter, MyCompany.SharePoint.WebPartPages.MobileAdapters, Version=1.0.0.0, Culture=neutral, PublicKeyToken=yourAssemblyPublicToken" />
用您的公司名称替换两处 MyCompany。用您的程序集公钥标记替换 yourAssemblyPublicKeyToken。可通过单击 Visual Studio 的"工具"菜单上的"获取程序集公钥"项来获取程序集公钥标记。公钥将显示在"输出"窗口中。(如果未显示该项,请参阅如何:创建用于获取程序集公钥的工具。)
备注
如果开发环境是多服务器场,则需要在所有服务器上编辑 compat.browser 文件。有关如何以编程方式执行此操作的信息,请参阅如何:在所有 Web 服务器上运行代码。
在开发计算机上将适配器注册为安全控件
右键单击"解决方案资源管理器"中的项目名称,选择"添加",然后选择"新建项目"。
备注
如果您在包含多个前端 Web 服务器的服务器场上进行开发,请不要使用此过程。而是应使用 SharePoint Foundation 解决方案部署适配器,并向解决方案的 manifest.xml 文件中添加一个 <SafeControl> 元素。有关 SharePoint Foundation 解决方案的详细信息,请参阅使用解决方案及其子主题。
在"添加新项目"对话框中,添加名为 webconfig.MyCompany.xml 的 XML 文件,其中 MyCompany 是您的公司名称,单击"添加"。
将以下标记添加到文件中。
<action> <remove path="configuration/SharePoint/SafeControls/SafeControl[@Assembly=MyCompany.SharePoint.WebPartPages.MobileAdapters3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=yourAssemblyPublicKeyToken']" /> <add path="configuration/SharePoint/SafeControls"> <SafeControl Assembly="MyCompany.SharePoint.WebPartPages.MobileAdapters3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=yourAssemblyPublicKeyToken" Namespace="MyCompany.SharePoint.WebPartPages.MobileAdapters3" TypeName="*" Safe="True" AllowRemoteDesigner="True" /> </add> </action>
用您的公司名称替换三处 MyCompany。用您在 compat.browser 文件标记中使用的相同公钥标记替换两处 yourAssemblyPublicKeyToken。
保存该文件。每次重新生成时,您将在后续步骤中创建的批处理文件都将执行两项操作。<add> 操作通过以下方法将您的适配器注册为安全控件:在开发计算机上所有 Web 应用程序的根目录中的所有 web.config 文件中添加指定的 <SafeControl> 元素。<remove> 操作在批处理文件第一次运行时不执行任何操作。在所有后续运行中,它将删除上次运行时所添加的 <SafeControl> 元素。这是必需的,因为重复的 <SafeControl> 元素可能会损坏 SharePoint Foundation 中的 Web 部件。
创建生成后批处理文件
右键单击"解决方案资源管理器"中的项目名称,选择"添加",然后选择"新建项目"。
在"添加新项目"对话框中,选择"文本文件",将其命名为 MobileAdapterPostBuild.bat,然后单击"添加"。
打开该文件并向其中添加以下行。
备注
此代码假定您遵循了如何:向 PATH 环境变量中添加工具位置中的建议。
gacutil if bin\debug\MyCompany.SharePoint.WebPartPages.MobileAdapters.dll xcopy /y webconfig.MyCompany.xml "C:\Program Files\Common Files\Microsoft Shared\web server extensions\14\CONFIG" stsadm –o copyappbincontent iisreset
在"文件"菜单上,单击"将 MobileAdapterPostBuild.bat 另存为..."。
在"文件另存为"对话框中,单击"保存"按钮旁边的向下箭头,并选择"编码保存"。
在"高级保存选项"对话框中,选择"编码"下拉列表中的"西欧(Windows) – 代码页 1252",然后单击"确定"。
此文件可确保每当重新生成项目时,最新版本的项目文件都会复制到正确的位置,并可确保您的适配器类注册为安全控件。它还会重新启动 SharePoint Foundation 以便加载最新版本的程序集。
重新生成解决方案
- 在 Visual Studio 的"生成"菜单上选择"重新生成解决方案"。
测试适配器
以下过程介绍了如何测试适配器。
使用 User Tasks Web 部件创建自定义 Web 部件页
在计算机浏览器中,导航到要从移动设备访问的网站。该网站就是您用其名称替换 CreateControlsForDetailView() 重写代码中的 CustomSite 的网站。
在 SharePoint Foundation UI 中,创建一个 Web 部件页并将 User Tasks Web 部件添加到其中。这些步骤如下所示:
在"网站操作"菜单上,选择"更多创建选项"。
在"创建"页上,单击"Web 部件页"。
在"新建 Web 部件页"页上,将新页面命名为"MyWPpage"并选择任何所需的布局模板。
在网站中选择所需的任何文档库(如"共享文档"),然后单击"创建"。新页面将在编辑模式中打开。
选择页面上的任何 Web 部件区域(如"右栏"),然后单击编辑功能区上方的"插入"。
在打开的页面上,单击"类别"区域中的"人员"。
选择"Web 部件"区域中的"User Tasks",然后单击"添加"。
单击"停止编辑"以查看包含 User Tasks Web 部件的页面的外观。然后立即继续执行下一过程。
填充网站的任务列表
从网站上的任何标准网站页中,单击左侧导航栏上的"任务"。
在"任务"页上,打开"项目"选项卡。
单击功能区上的"新建项目"以打开"新建项目"窗体。填写该窗体以创建新任务,然后单击"保存"。重复该步骤,为多名用户创建多个任务。应至少为每名用户分配四项或更多任务。
打开"浏览"选项卡以查看填充的列表的外观。
安装、配置和使用移动设备仿真程序
如果您尚未安装和配置移动设备仿真程序,请按设置移动设备仿真器中所述,在与您的开发服务器或服务器场具有网络连接的任何计算机上,安装和配置移动设备仿真程序。该计算机可以是您的开发计算机。
以您向其分配任务的某一用户的身份登录到该计算机,并按设置移动设备仿真器中的"启动仿真程序"过程所述,在仿真程序上启动浏览器。
导航到您的自定义 Web 部件页。所涉及的步骤因您的网站类型而异。通常,主页具有一个"查看所有网站内容"链接。而该链接页又具有一个指向网站文档库(如"共享文档")的链接。文档库的"所有文档"列表包含一个指向您的自定义 Web 部件页的链接。
页面的移动版本将以折叠(不是关闭)状态打开,其中包含已针对移动版本进行调整的所有 Web 部件。没有移动适配器的 Web 部件,或者已经在 Web 部件页的常规(非移动)版本上关闭的 Web 部件根本不会显示。在 SharePoint Foundation 中,关闭 Web 部件意味着隐藏该部件。(如果页面上没有符合移动可见性所需条件的 Web 部件,则该页面将不会打开,而是打开"所有网站内容"页面的移动版本。)图 1 显示了 User Task Web 部件是唯一一个没有关闭且具有移动适配器的 Web 部件的 Web 部件页。该图像是使用 Windows Mobile 5.0 Pocket PC 仿真程序生成的。
图 1. 移动设备上处于折叠状态的 User Tasks Web 部件。
单击"User Tasks"旁边的箭头图标可展开该 Web 部件。图 2 显示了按本主题所述进行调整后,为拥有少于四个分配任务的用户展开的 Web 部件。请注意,列表末尾没有"All my tasks"链接。还请注意,只列出了当前用户的任务。
图 2. 移动设备上处于展开状态的 User Tasks Web 部件。
图 3 显示了为拥有三个以上分配任务的用户展开的 Web 部件。请注意,只列出了三项任务,并且它们后面跟有"All my tasks"链接。这将打开"Tasks"列表的"My Tasks"视图。同样,还是只列出了当前用户的任务。
图 3. 为拥有三个以上分配任务的用户展开的 User Tasks Web 部件。