从 Pocket PC 访问 Microsoft Project Server 时间表数据

    技术2022-05-11  36

    简介

    在 Microsoft? Project 2002 的所有功能中,查看与时间表相关的数据可能是项目组成员最常使用的一项功能。这是因为时间表数据本身经常更改,并且基本上该数据被用作了一种衡量进度的手段。本质上说,时间表数据是所有项目组成员协作以完成各自分配任务的记录。项目组成员通常要在每天工作开始时查看分配给他们的所有任务(包括新任务),以便更好地调整和计划以实现目标。当组成员始终如一地更新他们的任务完成值时,项目经理就能够密切地跟踪项目的整体进度。

    桌面应用程序和移动应用程序间的差距已经显著缩小,这得益于每一次 Pocket PC 硬件和软件的向前飞跃。最新版本的 Pocket PC 2003 包括很多高级功能,这些功能可以使移动设备成为众多组织不可或缺的工具。随着 Microsoft Visual Studio? .NET 2003 的发布,创建智能设备应用程序变得更加简便。如同通过几次鼠标单击就可以创建控制台和 Windows 应用程序一样,您也可以以同样轻松的方式创建成熟的 Pocket PC 应用程序。

    Microsoft .NET 技术每天都在不断壮大,越来越多的复杂解决方案都是利用这种易用且强大的基础开发出来的。Microsoft .NET 的目标之一就是将这种技术拓展到多种平台。随着个人设备(例如 Pocket PC)采用的快速增长,看到对这些设备越来越多的 .NET 支持也就不足为奇了。实际上,随着 Visual Studio .NET 2003 的发布,.NET Compact Framework 进入到了由开发人员评估的阶段。.NET Compact Framework (CF) 允许开发人员使用用于移动设备的 .NET 公共库,使用方式与用于桌面应用程序的 .NET 公共库相同。尽管精简到了最基本的内容,CF 仍然是用于构建应用程序的强大框架。利用其对 Web 服务的支持,CF 为开发人员开启了新的探索令人兴奋的机会之门。

    通过其可扩展标记语言 (XML) 接口和扩展性模型,PDS 扩展使得添加用于检索和更新项目数据的自定义功能变得非常简单而且更加安全。如果自定义的客户端应用程序要求访问 Microsoft Project Server 数据,但同时该应用程序又无法使用 Microsoft Project 对象模型,则 PDS 扩展是用于这类应用程序的最佳选择。在本练习中,将创建自定义时间表 PDS 扩展来检索项目成员的时间表数据,同时该扩展还具有更新这些数据的功能。自定义时间表 PDS 扩展安装在运行 Microsoft Project Server 的服务器计算机上,可以由使用 SOAP 通讯的任意客户端应用程序使用。这就为所有使用 HTTP 连接的客户端应用程序提供了一种理想的接口。

    本练习的目的是使用运行在 Pocket PC 2002 设备上的 Microsoft .NET Compact Framework 来创建一个展示 Microsoft Project 时间表的移动应用程序。这不仅让项目组成员清楚已分配给他们的任务,还可以在网络连接可用时上载他们当天完成的任务。

    本文将说明如何使用 Visual Studio .NET 2003 创建智能设备应用程序,以及如何登录到 Microsoft Project Server 并使用自定义时间表 PDS 扩展。可以通过两种方式登录到 Microsoft Project Server;您的管理员可以选择使用 Windows 身份验证或 Microsoft Project Server 身份验证来验证您的帐户。因为 .NET Compact Framework 没有提供 Windows 身份验证,所以本文将说明如何使用 Microsoft Project Server 身份验证进行登录。此外,.NET Compact Framework 并不支持 HTTP Cookie,而这对于登录到 Microsoft Project Server 来说是必需的。通过创建代理中间方协助您获得对时间表数据的访问权,可以解决这个限制。

    本文假设您熟悉 Microsoft Project Server、Microsoft Project PDS 扩展、.NET Compact Framework 以及 Visual Studio .NET 2003 的工作方式。常规的 Pocket PC 开发经验以及对 SOAP、XML 和 Web 服务的基本理解也非常有用。

    入门

    第一步就是要熟悉 Microsoft Project Server 2002。假设您的公司已经安装了 Microsoft Project Server 2002,并且管理员(如果是除您自己之外的其他人)已经为您创建了一个使用 Microsoft Project Server 身份验证的帐户。特别要研究一下“时间表”视图,仔细查看多项任务和多个项目。在准备好后,您应该已经熟悉了 PDS 扩展以及客户端应用程序使用它们的方式。最后,密切关注由 ADO.NET 提供的 DataSet 类,因为本练习将通过使用该类来演示说明如何管理下载的时间表数据。

    在下载附带的源代码后,您会发现其中包括几个用于构建本练习的软件包。您需要仔细遵循安装说明,以确保正确的构建和正确的交互。密切关注将下面讨论的 Internet 信息服务 (IIS) 权限和 URL 设置,这些权限和设置反映您的开发环境。

    代理 Web 服务项目是使用 Visual Studio .NET 2002(版本 7.0)创建的。可以使用该版本或者使用 Visual Studio .NET 2003(版本 7.1)来构建和部署该代理 Web 服务。

    在可以使用代理 Web 服务之前,还需要更改几个 Microsoft Project Server 文件的权限设置。因为代理 Web 服务利用匿名访问调用 Timesheet PDS Extender,所以必须要授予下面所列出的 Microsoft Project Server 文件匿名访问权限。这样做是一种很好的折中方式,您不用对每个人打开所有 Microsoft Project Server 数据,而是略微放松限制以允许 Pocket PC 来访问您想要的数据。

    要授予匿名访问:

    1.

    在安装有 Microsoft Project Server 2002 的计算机上,打开 Internet Information Services (IIS),然后展开左侧的树,直到看到 ProjectServer。选择 ProjectServer 以显示所有的 Web 页和子文件夹。

    2.

    找到并右键单击文件 LGNPS.ASP,然后从 Context 菜单中选择 Properties。

    3.

    单击 File Security,然后在匿名访问和身份验证控制组中单击 Edit。

    4.

    选中 Anonymous access 和 Integrated Windows Authentication 复选框,然后单击 OK。

    5.

    对于其余的文件 SESSTART.ASP、PDS.WSDL 和 PDS.WSML 重复第 2 步到第 4 步。

    要注册 Timesheet PDS Extender:

    Timesheet PDS Extender 包括在下载中。Visual Basic 6.0 项目源代码也包括在其中,同时还有已编译的 TimesheetPDSExt.dll。在进行任何其他操作前,必须在 Microsoft Project Server 上注册该 DLL。有关 Microsoft Project 软件开发工具包 (SDK) 文档中的其他示例,请参考安装和注册 PDS Extender 的说明。

    要构建项目时间表代理 Web 服务:

    1.

    打开 Microsoft Internet 信息服务 (IIS),然后展开左侧的树,直到出现 Default Web Site。右键单击 Default Web Site,然后单击 New,再单击 Context 菜单上的 Virtual Directory。

    2.

    在“虚拟目录创建向导”中,单击 Next,在 Alias 字段中键入 ProjectTimesheetPDSProxy,然后单击 Next。

    3.

    在 Directory 字段中,输入项目文件驻留的文件夹(例如,local_drive:/ProjectTimesheetPDSProxy)。单击 Next。

    4.

    接受 Access Permissions 中的默认设置,单击 Next,然后单击 Finish。

    5.

    启动 Visual Studio .NET 2002 或 Visual Studio .NET 2003,在 File 菜单上,选择 Open,然后导航到 Projects。

    6.

    在 Open Project 对话框中,导航到放置 ProjectTimesheetPDSProxy.csproj 的文件夹,然后选择该文件。

    注 Visual Studio .NET 2003 会询问是否要转换该项目文件。这种转换过程是不可逆转的,因此如果继续,您将无法使用 Visual Studio .NET 2002 打开该项目。

    7.

    在“解决方案管理器”视图中,展开 WebReference。

    8.

    右键单击 WSPds,然后选择 Properties。

    9.

    在 Web Reference URL 字段中,输入 PDS.WSDL 文件的 URL(例如,http://local_host/project_server/pds.wsdl)。

    10.

    在 Build 菜单中,单击 Build Solution。

    要构建移动时间表应用程序:

    1.

    启动 Visual Studio .NET 2003。在 File 菜单上,单击 Open,然后导航到 Projects。

    2.

    在 Open Project 对话框中,导航到放置 MobileTimesheet.csdproj 的文件夹,然后选择该文件。

    3.

    在“解决方案管理器”视图中,展开 WebReference。

    4.

    右键单击 WSProjectTimesheet,然后单击 Properties。

    5.

    在 Web Reference URL 字段中,输入反映代理 Web 服务的 URL(例如,http://server_name/ProjectTimesheetPDSProxy/WSTimesheetPDS.asmx)。

    6.

    在 Build 菜单中,选择 BuildSolution。

    7.

    单击 Debug 菜单上的 Start,将该应用程序部署到 Pocket PC 设备或 Pocket PC 模拟器。

    8.

    还可以使用 Microsoft ActiveSync 中提供的 Explorer 功能,选择手动将 MobileTimesheet.exe 复制到 Pocket PC 中。

    在成功安装了上述所有组件后,请花一点时间来熟悉移动时间表应用程序。将重点放在登录到运行 Microsoft Project Server 的服务器并下载时间表数据上。同时,对任务进行一些更改并上载数据。使用 Microsoft Project Web Access 来验证已更改的任务值。以下各部分将详细说明如何构建完整的移动时间表应用程序。

    项目时间表

    Microsoft Project Web Access 为每个具有已分配任务的项目组成员提供了 My Tasks 视图。每个任务都按照任务名、其分配的持续时间以及其开始和结束日期进行说明。除本文重点介绍的几种属性外,还有其他的属性。尤其是,ActualWork、RemainingWork 和 PercentWorkComplete 是项目组成员通常在其移动设备上最喜查看和更改的属性。使用刚安装的自定义 Timesheet PDS Extender,现在就可以从移动设备访问您的时间表数据了。只有在项目经理已经将分配给您的任务发布到 Microsoft Project Server 之后,该数据才可用;它与 Microsoft Project Web Access 的“查看我的任务”页面上的数据相同。您或许希望花一点时间来研究 PDS Extender 的工作方式,因为这有助于理解时间表值和数据格式。

    Microsoft Project 2002 SDK 还提供了两个 PDS 测试工具,利用它们,您可以运行自定义 PDS 扩展来测试功能和预计结果。可以从 Microsoft 下载 PDS Test Application 和 PDS Test.NET Application。在注册 Timesheet PDS 扩展并配置 PDS 测试工具后,您就可以运行这些方法来检索并保存时间表数据。可以使用以下 XML 来调用 AssignmentsGet 方法。

     <Request>  <AssignmentsGet>    <AllAssignments>1</AllAssignments>  </AssignmentsGet></Request>

    如果存在给您分配的任务,则生成的 XML 应该类似于下面的数据。

    <Reply>  <HRESULT>0</HRESULT>  <STATUS>0</STATUS>  <AssignmentsGet>    <Assignments>      <Count>1</Count>      <Assignment>        <UID>109</UID>        <ProjectName>Software Development</ProjectName>        <TaskName>Secure project sponsorship</TaskName>        <Work>8</Work>        <ActualWork>0</ActualWork>        <RemainingWork>8</RemainingWork>        <PercentWorkComplete>0</PercentWorkComplete>        <Start>1/1/2003 1:00:00 PM</Start>        <Finish>1/2/2003 12:00:00 PM</Finish>        <CurrentTrackingMode>2</CurrentTrackingMode>        <Comments />      </Assignment>    </Assignments>  </AssignmentsGet></Reply>

    Assignment 节点代表一项任务,并且该节点包含说明该任务的属性。每项任务都由 UID 节点(来自 Microsoft Project Server 数据库中 MSP_WEB_ASSIGNMENTS 表的唯一值)确定,并且由 ProjectName 值分类。在组织时间表视图以用于显示和更新时,UID 和 ProjectName 节点值都是必需的。实际上,ActualWork、RemainingWork 和 PercentWorkComplete 值就是正在进行特定任务时每个项目组成员需要更新的值。Start 和 Finish 字段对于传达特定任务的时间窗口也非常有用。其余字段并未在本文中进行阐述。

    正如您所见,时间表数据以简单的 XML 表示,这意味着不存在说明每个节点的 XML 架构。对于类似于这样的简单数据组织,没有包括架构的迫切需要。您将会在稍后部分发现,.NET Data 类可以派生出一个架构,这样,通过将这些类用于表格、行和列,您就可以操作时间表数据了。目前,请记住时间表数据以简单的、基于标记的 XML 格式表示。

    同样地,通过以下 XML,您可以运行 AssignmentsSave 方法。

    <Request>  <AssignmentsSave>    <Assignments>      <Assignment>        <UID>109</UID>         <ActualWork>2</ActualWork>        <RemainingWork>6</RemainingWork>        <PercentWorkComplete>25</PercentWorkComplete>      </Assignment>    </Assignments>  </AssignmentsSave></Request>

    要提交任务更改,只需通过提供 UID 节点指出要更新的任务,然后填写为该特定任务所制定的进度。然后,Timesheet PDS Extender 会正确处理所有数据更新。可以通过 Microsoft 项目时间表视图来验证您的更新。

    创建 Pocket PC 应用程序

    在 Visual Studio .NET 2003 中创建智能设备应用程序与创建运行在桌面上的应用程序一样简单。主要区别在于您使用的是 .NET Compact Framework 而不是完整的 Microsoft .NET Framework v1.1。尽管这两种框架之间存在着显著的差异,但是您会发现移动时间表应用程序中实现的功能完全受 .NET Compact Framework 的支持。在启动 Visual Studio 后,您就可以创建 Pocket PC 应用程序了。

    要创建智能设备应用程序:

    1.

    在 File 菜单上,单击 New,然后导航到 Projects。

    2.

    在 New Project 对话框中,单击 Visual C# Projects,然后单击 Smart Device Application。

    3.

    在 Name 字段中,键入 MobileTimesheet。

    4.

    在 Location Field 中为项目输入一个值,然后单击 OK。

    5.

    在“智能设备应用程序向导”对话框中,针对平台选择 Pocket PC,针对项目类型选择 Windows Application,然后单击 OK。

    “新项目向导”会创建一个单窗体应用程序,以备于构建和部署到您的 Pocket PC。如果没有物理的 Pocket PC 设备,则可以始终将其部署到内置的模拟器中。在这两种情况下,Visual Studio 允许您设置断点并调试应用程序,如同针对桌面应用程序一样。

    具备了基本应用程序后,下一步就要为该应用程序创建菜单。

    要创建应用程序菜单:

    1.

    C# 文件的给定默认名为 Form1.cs。重命名该文件为 frmMain.cs,以更好地指示出其内容并有助于组织项目文件。

    2.

    双击 frmMain.cs 以激活“窗体设计器”视图。

    3.

    在 Windows Forms 窗格中,单击 View 菜单,然后选择 Toolbox 以查看可能要在该窗体上使用的控件的集合。

    4.

    双击 Toolbox 中的 MainMenu 控件将菜单添加到窗体;它将作为 mainMenu1 被添加到 Design 窗口的底部面板。

    5.

    右键单击 mainMenu1,然后选择 Edit Menu 将两个菜单项添加到窗体上:Main 和 Project。

    6.

    对于 Main 菜单,将 Download 和 Exit 定义为菜单项。

    7.

    目前,请保留 Project 菜单不动。您将在下载时间表数据时动态地构建 Project 菜单项。

    在这些添加完成后,就可以转到下一步设置应用程序的后端支持。

    创建 PDS 代理 Web 服务

    在可以从 Microsoft Project Server 提取时间表数据前,首先必须登录。前面提到过的 PDS 测试工具说明了如何以编程方式登录到 Microsoft Project Server。将其作为指导来检查登录的过程。您可能已经发现身份验证结果被存储在了 Cookie 中。这样 Microsoft Project Server 就可以在您查询信息和更新项目数据时维护会话状态。实际上,在您发出方法请求(例如,AssignmentsGet 和 AssignmentsSave)时,Timesheet PDS Extender 将要求 Cookie 字符串。

    .NET Compact Framework 提供了对智能设备非常有用的常见功能,同时又只占用最少的资源。这些最少资源使用的要求最终意味着,与完整的 .NET Framework 相比,.NET Compact Framework 会缺少非常多的功能。缺少的 HTTP 功能之一就是对 Cookie 的支持。尽管这意味着没有登录到 Microsoft Project Server 的直接方法,但您仍然可以创建一个简单的代理服务来为您处理 Cookie 支持。

    您将要创建的代理 Web 服务会为 Pocket PC 应用程序和 Microsoft Project Server 之间的数据流搭建一个桥梁。这种 Web 服务的主要目的在于启用 Cookie 处理,进而允许 Pocket PC 应用程序登录到 Microsoft Project Server 并进行 Timesheet PDS 调用。该 Web 服务可以部署在符合以下两个要求的任意计算机上:它运行 .NET Framework,同时可以由 Pocket PC 应用程序访问并且可以访问 Microsoft Project Server。创建这种代理 Web 服务的最简单的方法就是使用 Visual Studio .NET 2003,也可以使用 Visual Studio .NET 2002。

    要创建 PDS 代理 Web 服务:

    1.

    在 File 菜单上,单击 New,然后导航到 Projects。

    2.

    在“新建项目”对话框中,单击 Visual C# Projects,然后单击 ASP.NET Web Service。

    3.

    在 Name 字段,键入 ProjectTimesheetPDSProxy。

    4.

    为项目输入一个 Location,然后单击 OK。

    “新建项目向导”会创建一个 Web 虚拟根并且设置所有必要的文件,以便开始定义 Web 方法。代理 Web 服务只要求两个方法:登录到 Microsoft Project Server和 PDS 请求。使用附带的源代码检查 LoginToProjectServer 方法,并注意 HttpWebRequest 类的 CookieContainer 属性是捕获 Cookie 的必要元素。.NET Compact Framework 并不支持该属性。实际的 Cookie 字符串提取自 HttpWebResponse 的值,然后返回到调用方以便在随后的 PDS 请求上使用。

    构建和测试代理 Web 服务,然后就可以转到下一步从 Pocket PC 应用程序使用该 Web 服务了。

    添加 Web 服务

    将代理 Web 服务添加到 Pocket PC 应用程序非常简单。可以通过选择 Project 菜单上的 Add Web Reference,在 Visual Studio 中实现该操作。Add Web Reference 对话框为您提供了几种定位 Web 服务的方法。因为您刚创建了代理 Web 服务,只需简单地输入以下 URL,然后单击 Go 即可。

    http://server_name/ProjectTimesheetPDSProxy/WSTimesheetPDS.asmx

    Add Web Reference 对话框会显示由代理 Web 服务公布的两个方法。将默认名称 WebService1 重命名为 WSTimesheetPDS,然后单击 Add Reference。“添加 Web 参考向导”会为您生成所有必要的文件。请记住,您刚添加的 WSTimesheetPDS Web 服务就是代理 Web 服务,因此没有直接发出到 Timesheet PDS 的 SOAP 请求。而是代理 Web 服务将 Pocket PC 的请求委派给 Microsoft Project Server。对用户而言最终结果一目了然,即使间接请求略显效率低下。

    项目时间表窗体

    在完成代理 Web 服务后,就可以使用其服务并构建逻辑以便下载时间表数据。但是,在进行之前,应该考虑如何显示时间表数据。请花一点时间来研究一下 Microsoft Project Web Access 中的“时间表”视图。本质上,Pocket PC 在显示和使用上都可能引起对用户界面设计的挑战。因为受限的屏幕空间,所以请务必确保不要强迫用户不断地滚动屏幕。同样,还应该考虑如何捕获数据输入,例如执行的任务。

    在本部分中,您要创建一个驻留在现有 frmMain 窗体中的 ListView 用户界面元素。在 ListView 控件中,应该定义显示每列名称的列标题,必须指定控制使用行为的几个属性,同时还要提供对已更改数据的反馈。

    要创建 ListView 控件:

    1.

    在“解决方案管理器”视图中,双击 frmMain.cs 以显示“窗体设计器”视图。

    2.

    在 View 菜单上,单击 Toolbox。

    3.

    单击并将 ListView 控件从 Toolbox 拖动到 frmMain。

    4.

    右键单击 ListView 控件,然后单击 Properties。

    5.

    将 FullRowSelect 设置为 True。

    6.

    将 View 设置为 Details。

    7.

    在 Behavior 部分下,单击 Columns 字段的 (Collection),然后单击省略号 (??) 按钮。

    8.

    按照在 Mobile Timesheet 应用程序中的指示添加每列。

    9.

    在 Design 部分下,键入 (Name) 属性的 lstTasks。

    10.

    将 Location 设置为 4,4。

    11.

    将 Size 设置为 232,260。

    现在,您需要定义在用户选择列表行时的行为。返回到 lstTasks 的“属性”视图,在工具栏上找到 Events 图标。如果将鼠标悬停在该图标上,工具提示应该显示“事件”。如果单击该图标,应该出现 Behavior 部分。只有两个行为可用于 ListView 控件,即 ItemCheck 和 SelectedIndexChanged。“时间表”视图不使用任何复选框控件,因此可以忽略 ItemCheck 行为。为了更改任务工作更为有效,就地编辑行项目较为理想,但这种支持并未直接提供。这就使得 SelectedIndexChanged 行为成为捕获列表行上用户操作的唯一选项。正如其名称所示,SelectedIndexChanged 事件只有在用户选择的行不是当前选定行时才进行广播。因此,如果开始并没有选定行,那么选择行就会触发该事件进行广播。但是,单击相同的选定行不会触发该事件。请记住这种限制,因为您需要一个解决方案来允许用户重复地选择相同的行。该主题将会在“更新时间表数据”节中进一步讨论。

    要定义 ListView 行为:

    1.

    激活 lstTasks 的 Properties 视图,然后单击“事件”图标。

    2.

    在“行为”部分下,在 SelectedIndexChanged 字段旁边键入 lstTasks_SelectedIndexChanged。

    要完成 ListView 控件的规范,您必须定义要与其相关联的 ImageList 控件。该图像控件存在的唯一原因就是当特定行发生更改时为用户提供某种视觉反馈。因为 .NET Compact Framework 当前并不支持任何字体属性,对于指示已更改的数据,显示图标是一种很好的替代方法。绑定 ImageList 控件要求首先创建图像。您可以在绘图程序(例如,Microsoft 画图)中创建简单的图像,然后将文件保存为位图、jpeg、gif 或图标。图像的尺寸应该为 16×16 像素。

    要创建并绑定 ImageList 控件:

    1.

    仍然在 frmMain.cs 的窗体设计视图中,在 View 菜单上,单击 Toolbox。

    2.

    单击并将 ImageList 控件从 Toolbox 拖动到 frmMain。

    3.

    右键单击显示在窗体设计视图底部窗格上的 imageList1,然后单击 Properties。

    4.

    在 (Name) 字段的 Design 部分下,键入 imageListSmall。

    5.

    在 Appearance 部分下,单击 (Collection) 字段中的 . . . 按钮。

    6.

    在 Image Collection Editor 对话框中,单击 Add。

    7.

    选择刚才保存的图像文件,然后单击 OK。

    8.

    单击 lstTasks 的 Properties 视图。

    9.

    在 Behavior 部分下,指向 SmallImageList 旁边的下拉列表,然后单击 imageListSmall。

    关闭“窗体设计器”视图时,会为您生成所有必要的代码。这包括新增的私有函数 lstTasks_SelectedIndexChanged 以及图像列表关联。请花一点时间来研究一下 frmMain.cs 中名为 Windows Form Designer generated code 的区域内所列出的代码。

    登录到 Microsoft Project Server

    在可以访问时间表数据之前,您必须登录到运行 Microsoft Project Server 的服务器上。因为已经添加了代理 Web 服务来协助您进行登录,现在需要的就是获得用户的用户名和密码。为了帮助您完成该操作,移动时间表应用程序包括了一个带有两个文本项的模式对话框,以便捕获用于身份验证的登录凭据。

    在 Visual Studio .NET 2003 中,通过选择 Project 菜单,然后单击 Add Windows Form,您可以将新窗体添加到项目中。这会显示 Add New Item 对话框,其中您可以接受默认值或创建一个新项。使用包括在移动时间表应用程序中的 frmLogin.cs 中的窗体作为创建窗体的指导。

    在具有捕获用户凭据的能力后,可以创建代理 Web 服务类 WSProjectTimesheet.WSTimesheetPDS 的实例,然后通过借助于用户凭据调用 LoginToProjectServer 进行登录。sUserName 和 sPassword 值应该是您从登录窗体中获得的值。

    WSProjectTimesheet.WSTimesheetPDS ws;ws = new WSProjectTimesheet.WSTimesheetPDS();sCookie = ws.LoginToProjectServer(sUserName, sPassword);

    登录的结果将作为字符串返回。如果登录成功,本质上说,返回的字符串是一个要用于所有随后 PDS 调用的会话标识符。如果登录失败,则返回空字符串。您应该在 frmMain 中声明字符串变量 sCookie 以帮助管理与 Microsoft Project Server 的连接状态。只要用户选择下载或更新时间表数据,您就可以使用 sCookie 变量来检测用户是否需要登录到 Microsoft Project Server。

    检索时间表数据

    在成功登录到运行 Microsoft Project Server 的服务器之后,您就可以发出 AssignmentsGet PDS 方法来检索时间表数据。记住您已经为用户定义了启动下载过程的 Download 菜单项。请确保已经为该菜单项的 Click 事件声明了一个事件处理程序。

    要创建菜单项 click 事件处理程序:

    1.

    选择 frmMain.cs 的窗体设计视图,单击 View 菜单,然后单击 Toolbox。

    2.

    在主菜单上,右键单击 Download 菜单,然后单击 Properties。

    3.

    单击 Event 图标,然后在 Click 事件的旁边输入 menuDownload_Click。

    窗体设计器会创建私有函数 menuDownload_Click。这应该是放置逻辑以下载时间表数据的位置。正如上一部分所述,您应该使用 sCookie 变量检查用户是否首先需要执行登录。假设用户已经成功地获得到 Microsoft Project Server 的访问权或已经通过身份验证,那么现在您就具有了检索时间表数据所需要的所有信息。使用相同的代理 Web 服务登录到 Microsoft Project Server,调用 PdsRequest 方法为已通过身份验证的用户检索时间表数据。

    WSProjectTimesheet.WSTimesheetPDS ws;ws = new WSProjectTimesheet.WSTimesheetPDS();string sRequest = "<Request><AssignmentsGet>                  <AllAssignments>1</AllAssignments>                  </AssignmentsGet></Request>";string sTimesheetXml = ws.PdsRequest(sCookie, sRequest);

    返回的字符串应该包含 XML 格式的数据,如“项目时间表”部分中讨论的那样。访问该数据的最简单的方法之一就是使用 ADO.NET 中提供的 DataSet 类。DataSet 类的灵活性是无与伦比的。该类最重要的优势之一在于它可从 XML 格式的字符串构建包含行和列对象的表格。这允许您使用类型类对象,而不必解析字符串或使用 XML DOM。因为 DataSet 对象是用于访问和更改时间表数据的接口,您应该在 frmMain 中声明一个 DataSet 类型的变量 dsTimesheet。使用 ReadXml 方法来加载 DataSet 对象。

    DataSet dsTimesheet = new DataSet();StringReader sr = new StringReader(sTimesheetXml);dsTimesheet.ReadXml(new XmlTextReader(sr));

    请注意,有三种到 ReadXml 的重载方法。上面使用的方法接受 XmlReader 的派生类。该方法默认将 XmlReadMode 设置为 Auto。该方法的结果非常简单且完美,因为如果缺少一个架构,它会尝试推断一个。您将发现包含几个表的 dsTimesheet 数据集,您可以利用这些表格来查询架构以及数据。您使用的主要表格是分配表。该表包含反映任务属性的列。请花一点时间来研究 dsTimesheet 中提供的对象和集合。

    因为还希望允许用户对时间表进行更新,所以必须标记已修改的任务以确定哪些任务已经更改。这样会减少上载数据的量,只发送已更改任务。跟踪已更改任务的最简单的方法就是将 Changed 列添加到分配表中。还应该将已下载任务的 Changed 的默认值设置为 0。

    DataColumn dc;dc = new DataColumn("Changed",System.Type.GetType("System.Int32"));dsTimesheet.Tables["Assignment"].Columns.Add(dc);foreach(DataRow dr in dsTimesheet.Tables["Assignment"].Rows){   dr["Changed"] = 0;}

    生成时间表数据

    在设计窗体、指定列表视图并检索时间表数据后,您就可以显示时间表数据了。由于 Pocket PC 上受限的屏幕空间,您应该考虑以更容易管理的方式来组织任务列表。这样您已经指定的 Project 菜单就唾手可得了。记住在时间表数据中列出的每项任务还包含 ProjectName 属性。您可以按照任务的项目名来简单地对其进行分组,并且可以仅显示选定项目的任务。

    要从任务列表中提取所有不同的项目名,您必须在所有任务中进行循环访问,并手动执行名称比较。这是因为 DataTable.Select 方法不支持在 Microsoft SQL Server 中使用的 DISTINCT 筛选器,如在 Transact-SQL 中。对于已检索的每个不同的项目名,将与该项目对应的新菜单项添加到 Project 菜单。在构建 Project 菜单时,还要记住为菜单 Click 事件创建一个事件处理程序。下面的代码指定了一个私有方法 ShowProject 来接收每个项目菜单项的 Click 事件。

    string sPreviousProjectName = "";DataTable dt = dsTimesheet.Tables["Assignment"];DataRow[] drs = dt.Select(null, "ProjectName");foreach(DataRow dr in drs){   if (sPreviousProjectName != dr["ProjectName"].ToString()){MenuItem mi = new MenuItem();mi.Text = dr["ProjectName"].ToString();mi.Click += new System.EventHandler(this.ShowProject);menuProject.MenuItems.Add(mi);sPreviousProjectName = dr["ProjectName"].ToString();

    在用户从 Project 菜单中选择不同的项目时,您希望刷新时间表列表以显示选定项目的任务。ShowProject 方法事件处理程序应该首先移除列表视图中所有的现有列表行,然后添加属于选定项目的任务。下面的 projectName 变量等同于选定菜单项的文本。

    while (this.lstTasks.Items.Count > 0)  {   this.lstTasks.Items.RemoveAt(0);}string sFilter = "ProjectName = '" + projectName + "'";DataTable dt = dsTimesheet.Tables["Assignment"];DataRow[] taskRows = dt.Select(sFilter);foreach(DataRow dr in taskRows){   string[] str = new String[7]{dr["TaskName"].ToString(),            dr["Work"].ToString(),                            dr["PercentWorkComplete"].ToString(),                   dr["ActualWork"].ToString(),                        dr["RemainingWork"].ToString(),                      dr["Start"].ToString(),                              dr["Finish"].ToString()};   this.lstTasks.Items.Add(lstTaskItem);            }

    最后一步就是显示任务是否已经更改。因为已经为列表视图控件指定了一个图像列表,所以您可以使用语句 ListViewItem.ImageIndex = -1 将每个列表行设置为默认值以不显示任何图像。ImageList 是基于零的集合控件。索引 0 表示您希望列表行显示集合中的第一幅图像。同样地,索引 -1 表示不应该显示任何图像。

    脱机工作

    通常情况下,Pocket PC 用于脱机模式。电池寿命和可用网络连接通常被认为是不支持始终联机模式的主要原因。Pocket PC 的本质就是自由自在,不受办公室束缚,但仍然具有您所需要的生产工具的大多数功能。要利用移动时间表应用程序实现这个目标,您必须将对时间表的更改保留在 Pocket PC 上。

    DataSet 类还提供了将时间表数据写入文件的简单解决方案。因为所有时间表数据都存储在 dsTimesheet 对象中并在其中进行跟踪,所以可以使用 WriteXml 方法将所有数据刷新到一个文件中。重载 WriteXml 方法以使其带有两个变体。简便起见,可以通过指定完整路径、包括文件名的方法来选择写入到一个文件。还可以使用 System.Reflection 类确定移动时间表应用程序驻留的位置,然后将数据文件写入到相同的位置。

    string sTimesheetFile = System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase.Replace("MobileTimesheet.exe", "Timesheet.xml"); dsTimesheet.WriteXml(sTimesheetFile);

    在将数据写入到文件后,您可以使用任意文本编辑器来查看它。同样地,在使用 ReadXml 方法重新启动应用程序时,可以重新加载 dsTimesheet 数据集。通过提供相同的文件路径 sTimesheetFile,您可以非常容易地填充数据集。

    更新时间表数据

    在“项目时间表窗体”部分中,您学习了如何为 ListView 控件添加事件处理程序。该事件处理程序方法 lstTasks_SelectedIndexChanged 允许您指定当用户选择列表行时发生的情况。因为只有在列表行选择发生更改时才会触发该事件,所以您需要在处理该事件后清除选择以允许用户可以再次选择相同的行。可以通过设置 ListViewItem.Selected = False 来达到该目的。SelectedIndexChanged 事件的主要用途就是激活输入窗体,该窗体允许用户编辑选定任务的已完成工作量。记住每项任务都具有一个标识符 UID,您可以使用 ListView.SelectedIndices 在 Assignment 表中索引选定的行并通过 DataRow["UID"] 检索该标识符。

    正如创建用于捕获用户凭据的输入窗体一样,您应该创建一个任务编辑窗体来捕获已更改的值。同样,使用已下载的代码作为指导,您应该考虑到对 ActualWork、RemainingWork 和 PercentWorkCompleted 值的更改。请注意,这三个字段都由 Work 字段锁定,更改任何一个字段都将影响到其余字段的值。在完成该窗体后,您可以在用户单击列表行时显示它。如果用户提交了对任务的更改,您必须更新 dsTimesheet 中的值以反映已更改的数据。同样,您应该更新 ListViewItem.ImageIndex = 0 以指示特定任务已经更改。

    一旦检测到已更改的任务,无论是通过 Task Edit 窗体还是通过加载以前保存的时间表,您都应该将 Upload 菜单项添加到 Main 菜单中。正如为 Download 菜单添加事件处理程序一样,为 Upload 菜单创建一个事件处理程序。请记住,您应该在创建 Upload 菜单项和指定事件处理程序之前,检查该菜单项是否存在。分析附带的源代码中的 AddMenuUpload 方法。

    Upload 菜单项的存在也是一个用于已更改时间表数据的良好指示。实际上,当用户选择下载他的时间表时,您应该提供一个现有时间表数据已经更改的警告,并询问是否首先执行上载。通过使用 MenuItem.MenuItems 中的 Contains 方法,可以检查 Upload 菜单项。在您执行时间表上载前,还应该检查用户是否登录到 Microsoft Project Server。在下载时间表数据时也应该进行相同的检查。使用前面创建的 sCookie 变量来确定用户是否通过身份验证。

    请参考“项目时间表”部分,AssignmentsSave 和 AssignmentsProjectManagerUpdate PDS 方法说明了成功更新已更改的任务所需要构造的确切格式。因为 AssignmentsSave 和 AssignmentsProjectManagerUpdate 方法将更新在 XML 内容中指示的每项任务,所以您应该只发送标记有“Changed = 1”的任务。通过循环访问分配表中的每一行,您可以使用 StringBuilder 类来构建更新的 XML 字符串。

    StringBuilder sbTasks = new StringBuilder();sbTasks.Append("<Request><AssignmentsSave><Assignments>");StringBuilder sbManager = new StringBuilder();sbManager.Append("<Request><AssignmentsProjectManagerUpdate><Assignments>");foreach(DataRow dr in dsTimesheet.Tables["Assignment"].Rows){   if (dr["Changed"].ToString() != "0")   {      dr["Changed"] = 0;      sbTasks.Append("<Assignment><UID>" + dr["UID"].ToString() + "</UID>");      sbTasks.Append("<ActualWork>" + dr["ActualWork"].ToString() +      "</ActualWork>");      sbTasks.Append("<RemainingWork>" + dr["RemainingWork"].ToString() +       "</RemainingWork>");      sbTasks.Append("<PercentWorkComplete>" + dr["PercentWorkComplete"].ToString() +       "</PercentWorkComplete></Assignment>");      sbManager.Append("<Assignment><UID>" + dr["UID"].ToString() +       "</UID></Assignment>");   }}sbTasks.Append("</Assignments></AssignmentsSave></Request>");sbManager.Append("</Assignments></AssignmentsProjectManagerUpdate></Request>");WSProjectTimesheet.WSTimesheetPDS ws = new WSProjectTimesheet.WSTimesheetPDS();string sReplyXml = ws.PdsRequest(sCookie, sbTasks.ToString());sReplyXml = ws.PdsRequest(sCookie, sbManager.ToString());

    同样,使用代理 Web 服务 WSProjectTimesheet 来发送您所构建的用于更新 Microsoft Project Server 上的时间表数据的 XML 字符串。请注意,PdsRequest 方法与您用于检索时间表数据的方法相同。但是,此时您发送的 XML 字符串会命令 Timesheet PDS 更改特定用户的任务数据。

    WSProjectTimesheet.WSTimesheetPDS ws;ws = new WSProjectTimesheet.WSTimesheetPDS();ws.PdsRequest(sCookie, sb.ToString());

    在成功上载时间表数据后,您应该重置所有任务的 Changed 状态,并移除 Upload 菜单项。同样地,您应该重置 ImageIndex 以反映列表视图中未更改的任务。

    小结

    本文简要介绍了将 Microsoft Project 数据引入 Pocket PC 设备。通过进一步的探究和自定义 PDS 扩展,您自己可以轻松地增强自己的功能,包括跟踪问题以及查看由资源提交的任务更改。

     

    最新回复(0)