演练:创建移动适配器

上次修改时间: 2011年4月1日

适用范围: SharePoint Foundation 2010

本演练演示了如何为 Microsoft SharePoint Foundation 附带的 UserTasksWebPart 创建移动适配器。有关创建移动 Web 部件适配器的过程的更高级别讨论,请参阅如何创建移动适配器

先决条件

回顾主题SharePoint Foundation 开发工具及其子主题,并执行推荐的用于设置开发环境的任务。特别需要指出,本演练假定您已执行设置移动设备仿真器如何:创建用于获取程序集公钥的工具如何:向 PATH 环境变量中添加工具位置中推荐的任务。

开发适配器

以下步骤介绍了创建移动适配器的过程。

设置移动适配器项目

  1. 在 Visual Studio 中,选择"文件"菜单上的"新建",然后选择"项目"。

  2. 在"新建项目"对话框中,选择"项目类型"框中的"Visual C#",选择"模板"框中的"类库",然后在"名称"框中输入 MobileAdapters。单击"确定"。

  3. 右键单击"解决方案资源管理器"中的"引用"节点,单击"添加引用",然后在按住 Ctrl 键的同时,选择"添加引用"对话框中".NET"选项卡上的"System.Web"、"System.Web.Mobile"和"Microsoft.SharePoint"。单击"确定"。

  4. 右键单击"解决方案资源管理器"中的项目名称并选择"属性"。

  5. 在"属性"对话框的"应用程序"选项卡上,输入 MyCompany.SharePoint.WebPartPages.MobileAdapters 作为"程序集名称",输入 MyCompany.SharePoint.WebPartPages 作为"默认命名空间"。用您的公司名称替换 MyCompany。将本演练中的所有 MyCompany 都替换为您的公司名称。

  6. 单击"程序集信息"并根据需要在"程序集信息"对话框中进行更改。本演练假设您将程序集和文件版本保留为 1.0.0.0,并且您不更改 GUID。

  7. 打开"签名"选项卡,再选择"为程序集签名"。

  8. 从"选择强名称密钥文件"下拉列表框中选择"<新建...>"。

  9. 在"创建强名称密钥"对话框的"密钥文件名称"框中,键入 MobileAdapters.snk,然后确保 选中"项目..."复选框。单击"确定"。

  10. 打开"生成事件"选项卡,并在"后期生成事件命令行"框中键入以下代码。该代码将运行您在稍后步骤中创建的批处理文件。

    cd "$(ProjectDir)"
    MobileAdapterPostBuild
    
  11. 在工具栏上单击"保存所有文件"按钮。

  12. 在"解决方案资源管理器"中,将文件 Class1.cs 重命名为 UserTasksWebPartMobileAdapter.cs。

创建适配器控件

  1. 打开项目的 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
    
  2. 将命名空间更改为 MyCompany.SharePoint.WebPartPages.MobileAdapters。

  3. 用下面的代码替换整个 Class1 声明。

    public class UserTasksWebPartMobileAdapter : WebPartMobileAdapter
    {
    
    }// end UserTasksWebPartMobileAdapter class
    
    Public Class UserTasksWebPartMobileAdapter
    Inherits WebPartMobileAdapter
    
    End Class ' end UserTasksWebPartMobileAdapter class
    

    请注意,您的新类将继承自 WebPartMobileAdapter

  4. 添加重写 CreateControlsForDetailView() 方法的以下声明。

    protected override void CreateControlsForDetailView()
    {
    
    } // end CreateControlsForDetailView
    
    Protected Overrides Sub CreateControlsForDetailView()
    
    End Sub ' end CreateControlsForDetailView
    
  5. 使用以下行开始实现 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)
    
  6. 添加以下行以呈现 User Tasks Web 部件的默认标题,即以粗体显示的"User Tasks"。

    Label titleLabel = this.CreateWebPartLabel();
    this.Controls.Add(titleLabel);
    
    Dim titleLabel As Label = Me.CreateWebPartLabel()
    Me.Controls.Add(titleLabel)
    
  7. 添加以下行以收集对对象的引用,您的代码将在其呈现逻辑中引用这些对象。将 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)
    
  8. 添加以下 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.
    
  9. 添加 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"
    
  10. 在该循环内,添加以下代码以呈现标准的 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)
    
  11. 添加以下代码以呈现任务名称。请注意,Font() 是只读属性,它具有可写子属性,包括 BoldSize。不能使用对象初始值设定项语法设置这些子属性。

    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)
    
  12. 添加以下代码以便任务标题后跟以小字体显示的任务优先级。请注意,此处提到的 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)
    
  13. 添加以下代码以便在每个任务后面放置一个空行。

    this.Controls.Add(new LiteralText());
    
    Me.Controls.Add(New LiteralText())
    
  14. 最后,添加以下 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
    
  15. 在"生成"菜单上选择"生成解决方案"。尽管此时您尚未完成操作,但需要编译程序集,这样才能够生成公钥标记。

在 compat.browser 文件中注册移动适配器

  1. 在文本编辑器或 Visual Studio 中打开文件 \\Inetpub\wwwroot\wss\VirtualDirectories\80\App_Browsers\compat.browser,并滚动到 refID 属性值为"default"的 <browser> 元素。(如果需要,请用目标 Web 应用程序的端口替换 URL 中的"80"。)

  2. 在 <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 服务器上运行代码

在开发计算机上将适配器注册为安全控件

  1. 右键单击"解决方案资源管理器"中的项目名称,选择"添加",然后选择"新建项目"。

    备注

    如果您在包含多个前端 Web 服务器的服务器场上进行开发,请不要使用此过程。而是应使用 SharePoint Foundation 解决方案部署适配器,并向解决方案的 manifest.xml 文件中添加一个 <SafeControl> 元素。有关 SharePoint Foundation 解决方案的详细信息,请参阅使用解决方案及其子主题。

  2. 在"添加新项目"对话框中,添加名为 webconfig.MyCompany.xml 的 XML 文件,其中 MyCompany 是您的公司名称,单击"添加"。

  3. 将以下标记添加到文件中。

    <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。

  4. 保存该文件。每次重新生成时,您将在后续步骤中创建的批处理文件都将执行两项操作。<add> 操作通过以下方法将您的适配器注册为安全控件:在开发计算机上所有 Web 应用程序的根目录中的所有 web.config 文件中添加指定的 <SafeControl> 元素。<remove> 操作在批处理文件第一次运行时不执行任何操作。在所有后续运行中,它将删除上次运行时所添加的 <SafeControl> 元素。这是必需的,因为重复的 <SafeControl> 元素可能会损坏 SharePoint Foundation 中的 Web 部件。

创建生成后批处理文件

  1. 右键单击"解决方案资源管理器"中的项目名称,选择"添加",然后选择"新建项目"。

  2. 在"添加新项目"对话框中,选择"文本文件",将其命名为 MobileAdapterPostBuild.bat,然后单击"添加"。

  3. 打开该文件并向其中添加以下行。

    备注

    此代码假定您遵循了如何:向 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
    
  4. 在"文件"菜单上,单击"将 MobileAdapterPostBuild.bat 另存为..."。

  5. 在"文件另存为"对话框中,单击"保存"按钮旁边的向下箭头,并选择"编码保存"。

  6. 在"高级保存选项"对话框中,选择"编码"下拉列表中的"西欧(Windows) – 代码页 1252",然后单击"确定"。

    此文件可确保每当重新生成项目时,最新版本的项目文件都会复制到正确的位置,并可确保您的适配器类注册为安全控件。它还会重新启动 SharePoint Foundation 以便加载最新版本的程序集。

重新生成解决方案

  • 在 Visual Studio 的"生成"菜单上选择"重新生成解决方案"。

测试适配器

以下过程介绍了如何测试适配器。

使用 User Tasks Web 部件创建自定义 Web 部件页

  1. 在计算机浏览器中,导航到要从移动设备访问的网站。该网站就是您用其名称替换 CreateControlsForDetailView() 重写代码中的 CustomSite 的网站。

  2. 在 SharePoint Foundation UI 中,创建一个 Web 部件页并将 User Tasks Web 部件添加到其中。这些步骤如下所示:

    1. 在"网站操作"菜单上,选择"更多创建选项"。

    2. 在"创建"页上,单击"Web 部件页"。

    3. 在"新建 Web 部件页"页上,将新页面命名为"MyWPpage"并选择任何所需的布局模板。

    4. 在网站中选择所需的任何文档库(如"共享文档"),然后单击"创建"。新页面将在编辑模式中打开。

    5. 选择页面上的任何 Web 部件区域(如"右栏"),然后单击编辑功能区上方的"插入"。

    6. 在打开的页面上,单击"类别"区域中的"人员"。

    7. 选择"Web 部件"区域中的"User Tasks",然后单击"添加"。

    8. 单击"停止编辑"以查看包含 User Tasks Web 部件的页面的外观。然后立即继续执行下一过程。

填充网站的任务列表

  1. 从网站上的任何标准网站页中,单击左侧导航栏上的"任务"。

  2. 在"任务"页上,打开"项目"选项卡。

  3. 单击功能区上的"新建项目"以打开"新建项目"窗体。填写该窗体以创建新任务,然后单击"保存"。重复该步骤,为多名用户创建多个任务。应至少为每名用户分配四项或更多任务。

  4. 打开"浏览"选项卡以查看填充的列表的外观。

安装、配置和使用移动设备仿真程序

  1. 如果您尚未安装和配置移动设备仿真程序,请按设置移动设备仿真器中所述,在与您的开发服务器或服务器场具有网络连接的任何计算机上,安装和配置移动设备仿真程序。该计算机可以是您的开发计算机。

  2. 以您向其分配任务的某一用户的身份登录到该计算机,并按设置移动设备仿真器中的"启动仿真程序"过程所述,在仿真程序上启动浏览器。

  3. 导航到您的自定义 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 部件。

    折叠状态的用户任务移动适配器

  4. 单击"User Tasks"旁边的箭头图标可展开该 Web 部件。图 2 显示了按本主题所述进行调整后,为拥有少于四个分配任务的用户展开的 Web 部件。请注意,列表末尾没有"All my tasks"链接。还请注意,只列出了当前用户的任务。

    图 2. 移动设备上处于展开状态的 User Tasks Web 部件。

    扩展后的用户任务移动适配器

    图 3 显示了为拥有三个以上分配任务的用户展开的 Web 部件。请注意,只列出了三项任务,并且它们后面跟有"All my tasks"链接。这将打开"Tasks"列表的"My Tasks"视图。同样,还是只列出了当前用户的任务。

    图 3. 为拥有三个以上分配任务的用户展开的 User Tasks Web 部件。

    将用户任务 Web 适配器用于 3 个以上的任务