Accessing Microsoft Project Server Timesheet Data from the Pocket PC

This content is no longer actively maintained. It is provided as is, for anyone who may still be using these technologies, with no warranties or claims of accuracy with regard to the most recent product version or service release.

 

Microsoft Corporation

August 2003

Applies to:
    Microsoft®  Project Server 2002
    Microsoft Visual Studio® .NET 2002
    Microsoft Visual Studio .NET 2003
    Microsoft® .NET Compact Framework

Summary: Construct a Pocket PC application to view and change project timesheet data. The sample application is created using the Microsoft .NET Compact Framework, and uses Web services to access a custom Microsoft Project Data Service (PDS) extension. (18 printed pages)

The Microsoft Project 2002 Sample: Mobile Timesheet Extension file is available from the Microsoft Download Center.

Contents

Introduction
Getting Started
Project Timesheet
Create a Pocket PC Application
Create a PDS Proxy Web Service
Adding Web Services
Project Timesheet Forms
Working Offline
Update Timesheet Data
Conclusion References

Introduction

Of all the features in Microsoft® Project 2002, viewing timesheet-related data is perhaps the most often used by project team members. This is because the nature of timesheet data is constantly changing and is ultimately used as a measurement of progress. Timesheet data is essentially the record of the collaboration of all project team members working to complete their assigned tasks. Project team members typically want to view all tasks assigned to them, including new tasks, at the beginning of each day to better adjust and plan for achieving goals. When team members consistently update their task completion values, the project manager is able to closely track the overall progress of the project.

The gap between desktop and mobile applications has narrowed dramatically with each advancing generation of Pocket PC hardware and software. The latest version, Pocket PC 2003, is complete with advanced features that make mobile devices an indispensable tool for many organizations. With the release of Microsoft Visual Studio® .NET 2003, the ability to create smart device applications has become much easier. Just as console and Windows applications can be created with a few mouse clicks, a full-fledged Pocket PC application can likewise be created with the same ease.

Microsoft .NET technology gains new ground each day, as more sophisticated solutions are developed with this easy-to-use, but powerful foundation. One of the goals of Microsoft .NET is bringing this technology to a variety of platforms. With the fast-growing adoption of personal devices such as the Pocket PC, it should be no surprise to see increasing .NET support for these devices. In fact, with the release of Visual Studio .NET 2003, the .NET Compact Framework is going through another round of evaluation by developers. The .NET Compact Framework (CF) allows developers to work with the .NET common libraries for mobile devices in the same way as for a desktop application. Although pared down to just the essentials, CF is, nonetheless, a powerful framework for building applications. With its support for Web services, CF opens a new door for developers to explore exciting opportunities.

A PDS extension, with its Extensible Markup Language (XML) interface and extensibility model, makes adding customized functions for retrieving and updating project data very easy and more secure. PDS extensions are an excellent choice for custom client applications that require access to Microsoft Project Server data but cannot use the Microsoft Project Object Model. In this exercise, a custom timesheet PDS extension is created to retrieve a project member's timesheet data, as well as to have the ability to update them. The custom timesheet PDS extension is installed on a server computer running Microsoft Project Server and can be used by any client application using SOAP communication. This makes an ideal interface for any client application with an HTTP connection.

The goal of this exercise is to create a mobile application, using the Microsoft .NET Compact Framework running on a Pocket PC 2002 device, to showcase the Microsoft Project timesheet. Not only does this allow project team members to carry their assigned tasks with them, they can also upload the tasks that they have worked on throughout the day when a network connection is available.

This article describes how to use Visual Studio .NET 2003 to create a smart device application, as well as shows you how to log on to Microsoft Project Server and use the custom timesheet PDS extension. You can log on to Microsoft Project Server in two ways; your administrator can choose either Windows Authentication or Microsoft Project Server authentication to validate your account. Because the .NET Compact Framework does not offer Windows Authentication, this article shows you how to log on by using Microsoft Project Server authentication. In addition, the .NET Compact Framework does not support HTTP cookies, which are required to log on to Microsoft Project Server. You can work around this restriction by creating a proxy intermediary to help you gain access to your timesheet data.

This article assumes you have familiarity with the workings of Microsoft Project Server, Microsoft Project PDS extensions, .NET Compact Framework, as well as Visual Studio .NET 2003. General Pocket PC development experience is also helpful, as well as a basic understanding of SOAP, XML, and Web services.

Getting Started

The first step is to get acquainted with Microsoft Project Server 2002. It is assumed that your organization has already installed Microsoft Project Server 2002, and the administrator, if that is someone other than yourself, has created an account for you that uses Microsoft Project Server authentication. In particular, study the Timesheet view, scrutinizing multiple tasks and multiple projects. As you complete your preparation, you should familiarize yourself with PDS extensions and how a client application can use them. Finally, pay close attention to the DataSet class offered by ADO.NET, as this exercise demonstrates how the downloaded timesheet data is managed by using this class.

After you have downloaded the accompanying source code, you will find that there are several packages included for building this exercise. You need to follow the installation instructions carefully to ensure a proper build and proper interaction. Pay close attention to the Internet Information Services (IIS) permissions and URL settings discussed below to reflect your development environment.

The proxy Web service project was created using Visual Studio .NET 2002 (version 7.0). You can use either this version or Visual Studio .NET 2003 (version 7.1) to build and deploy the proxy Web service.

You will also need to change permissions settings for several Microsoft Project Server files before you can exercise the proxy Web service. Because the proxy Web service invokes the Timesheet PDS Extender with anonymous access, it is necessary to grant anonymous access permissions on the Microsoft Project Server files listed below. This is a fair compromise in that you are not opening all Microsoft Project Server data to everyone, but that you are instead relaxing the constraints a bit to allow your Pocket PC to access the data you want.

To grant anonymous access

  1. On the computer where Microsoft Project Server 2002 is installed, open Internet Information Services (IIS) and expand the tree on left until you see ProjectServer. Select ProjectServer to display all Web pages and subfolders.
  2. Locate and right-click the file LGNPS.ASP, and select Properties from the Context menu.
  3. Click File Security, and click Edit within the Anonymous access and authentication control group.
  4. Select the Anonymous access and the Integrated Windows Authentication check boxes, and click OK.
  5. Repeat steps 2 through 4 for the remaining files SESSTART.ASP, PDS.WSDL and PDS.WSML.

To register the Timesheet PDS Extender

The Timesheet PDS Extender is included with the download. The Visual Basic 6.0 project source code is also included, along with the compiled TimesheetPDSExt.dll. You must register this DLL on Microsoft Project Server before doing anything else. Refer to the instructions for installing and registering a PDS Extender for other samples in the Microsoft Project Software Development Kit (SDK) documentation.

To build the project timesheet proxy Web service

  1. Open Microsoft Internet Information Services (IIS) and expand the tree on the left until Default Web Site appears. Right-click Default Web Site and click New and then Virtual Directory on the Context menu.

  2. In the Virtual Directory Creation Wizard, click Next, type ProjectTimesheetPDSProxy in the Alias field, and then click Next.

  3. In the Directory field, enter the folder where the project files reside (for example, local_drive:\ProjectTimesheetPDSProxy). Click Next.

  4. Accept the default settings in Access Permissions, click Next, and then click Finish.

  5. Start either Visual Studio .NET 2002 or Visual Studio .NET 2003 and on the File menu, select Open and navigate to Projects.

  6. In the Open Project dialog box, navigate to the folder where you placed ProjectTimesheetPDSProxy.csproj, and select this file.

    Note   Visual Studio .NET 2003 asks if you want to convert this project file. This conversion process is not reversible, so if you proceed, you cannot open this project by using Visual Studio .NET 2002.

  7. In the Solution Explorer view, expand Web Reference.

  8. Right-click on WSPds and select Properties.

  9. In the Web Reference URL field, enter the URL for the PDS.WSDL file (for example, http://local_host/project_server/pds.wsdl).

  10. On the Build menu, click Build Solution.

To build the Mobile Timesheet application

  1. Start Visual Studio .NET 2003. On the File menu, click Open and navigate to Projects.
  2. In the Open Project dialog box, navigate to the folder where you placed MobileTimesheet.csdproj, and select this file.
  3. In the Solution Explorer view, expand Web Reference.
  4. Right-click WSProjectTimesheet, and click Properties.
  5. In the Web Reference URL field, enter a URL that reflects the proxy Web service (for example, http://server_name/ProjectTimesheetPDSProxy/WSTimesheetPDS.asmx).
  6. On the Build menu, select Build Solution.
  7. Click Start on the Debug menu to deploy this application to a Pocket PC Device or to a Pocket PC Emulator.
  8. You can also choose to manually copy MobileTimesheet.exe to your Pocket PC by using the Explorer feature provided in Microsoft ActiveSync.

Take a moment to get acquainted with the Mobile Timesheet application after you have successfully installed all of the above components. Focus on logging on to the server running Microsoft Project Server and downloading your timesheet data. Also, make some changes to your tasks and upload the data. Use Microsoft Project Web Access to verify the changed task values. The following sections show you in detail how to build a complete Mobile Timesheet application.

Project Timesheet

Microsoft Project Web Access provides a My Tasks view for each project team member with assigned tasks. Each task is described by the task name, its allocated duration, and its start and finish dates. There are other properties, but these are the ones that this article focuses on. In particular, ActualWork, RemainingWork, and PercentWorkComplete are the properties that project team members typically are most interested in viewing and changing on their mobile devices. Using the custom Timesheet PDS Extender that you have just installed, you now have access to your timesheet data from a mobile device. This data is available only after a project manager has published your assignments to Microsoft Project Server; it is the same data on the View my Tasks page of Microsoft Project Web Access. You may want to take a moment to study how the PDS Extender works, as it will help you understand both the timesheet values and the data format.

The Microsoft Project 2002 SDK also provides two PDS test tools that allow you to run the custom PDS extension to test for functionality and expected results. You can download the PDS Test Application or the PDS Test.NET Application from Microsoft. After you have registered the Timesheet PDS extension and configured the PDS test tool, you can run the methods to retrieve and save your timesheet data. The AssignmentsGet method can be invoked by using the following XML.

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

If there are tasks assigned to you, the resulting XML should be similar to the data below.

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

The Assignment node represents one task, and contains properties describing that task. Each task is identified by the UID node, a unique value from the MSP_WEB_ASSIGNMENTS table in the Microsoft Project Server database, and is categorized by the ProjectName value. Both the UID and ProjectName node values is essential, as you organize your timesheet view for display and update. The ActualWork, RemainingWork, and PercentWorkComplete values are effectively what each project member needs to update when a particular task has been worked on. The Start and Finish fields are also useful for conveying the time window for a particular task. The remaining fields are not addressed in this article.

As you can see, the timesheet data is represented in simple XML, meaning there is no XML schema describing each node. With simple data organization like this, there is no pressing need to include a schema. You will discover in a later section that the .NET Data classes can derive a schema so that you can manipulate timesheet data by using classes for tables, rows, and columns. For now, remember that your timesheet data is represented in the simple, tag-based XML format.

Similarly, you can run the AssignmentsSave method by issuing the following XML.

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

To submit task changes, simply indicate the task you want to update by supplying the UID node, and fill in the progress that you have made for this particular task. The Timesheet PDS Extender then handles all data updates correctly. You can verify your updates through the Microsoft Project Timesheet View.

Create a Pocket PC Application

Creating a smart device application in Visual Studio .NET 2003 is as simple as creating an application that runs on a desktop. The primary difference is that you are working with the .NET Compact Framework instead of the full Microsoft .NET Framework v1.1. Although there are significant differences between the frameworks, you will find that the features implemented in the Mobile Timesheet application are fully supported by the .NET Compact Framework. After you have started Visual Studio, you are ready to create a Pocket PC application.

To create a smart device application

  1. On the File menu, click New and navigate to Projects.
  2. In the New Project dialog box, click Visual C# Projects and then click Smart Device Application.
  3. In the Name field, type MobileTimesheet.
  4. Enter a value for the project in the Location Field and click OK.
  5. In the Smart Device Application Wizard dialog box, select Pocket PC for the Platform, and Windows Application for the Project Type, and click OK.

The New Projects Wizard creates a single-form application that is ready for you to build and deploy to your Pocket PC. If you do not have a physical Pocket PC device, you can always deploy to the built-in emulator. In either case, Visual Studio allows you to set break points and debug your application as you would for a desktop application.

With the basic application in place, the next step is to create the menus for this application.

To create application menus

  1. The C# file is given the default name Form1.cs. Rename the file to frmMain.cs to better indicate its contents and to help organize your project files.
  2. Double-click frmMain.cs to activate the Form Designer view.
  3. In the Windows Forms pane, click the View menu, and select Toolbox to see the collection of controls that may be used on the form.
  4. Double-click the MainMenu control in the Toolbox to add a menu to the form; it is added to the bottom panel of the Design window as mainMenu1.
  5. Right-click mainMenu1 and select Edit Menu to add two menu items on the form: Main and Project.
  6. For the Main menu, define Download and Exit as the menu items.
  7. Leave the Project menu as it is, for now. You will build the Project menu items dynamically as you download timesheet data.

With these additions in place, you are ready to move on to the next step of setting up the backend support for your application.

Create a PDS Proxy Web Service

Before the timesheet data can be extracted from Microsoft Project Server, you first must log on. The PDS test tools referenced above show how you can programmatically log on to Microsoft Project Server. Use this as a guide for examining the process of logging on. You probably have discovered that the authentication result is stored in a cookie. This is so that Microsoft Project Server maintains your session state as you query for information and make updates to project data. In fact, the Timesheet PDS Extender requires the cookie string when you make method requests such as AssignmentsGet and AssignmentsSave.

The .NET Compact Framework provides common features that are useful for smart devices, but at the same time consume minimal resources. These requirements for minimal resource usage ultimately mean that a significant number of features are absent on the .NET Compact Framework when compared to the full .NET Framework. One of the missing HTTP features is the support for cookies. While this means that there's no direct way to log on to Microsoft Project Server, you can still create a simple proxy service to handle cookie support for you.

The proxy Web service you are about to create bridges the data flow between the Pocket PC application and Microsoft Project Server. The primary purpose for this Web service is to enable cookie handling and allow the Pocket PC application to log on to Microsoft Project Server and make Timesheet PDS calls. This Web service can be deployed on any computer that meets the following two requirements: that it is running the .NET Framework, and that it is reachable by the Pocket PC application and can access Microsoft Project Server. The easiest way to create this proxy Web service is by using Visual Studio .NET 2003; you can also use Visual Studio .NET 2002.

To create a PDS proxy Web service

  1. On the File menu, click New and navigate to Projects.
  2. In the New Project dialog box, click Visual C# Projects and then click ASP.NET Web Service.
  3. In the Name field, type ProjectTimesheetPDSProxy.
  4. Enter a Location for the project and click OK.

The New Project Wizard creates a Web virtual root and set up all necessary files for you to begin defining the Web methods. The proxy Web service requires only two methods: a log on to Microsoft Project Server, and a PDS request. Using the accompanying source code, examine the LoginToProjectServer method and note that the CookieContainer property of the HttpWebRequest class is the necessary element for capturing cookies. The .NET Compact Framework does not support this property. The actual cookie string is extracted from the value of HttpWebResponse, and is then returned to the caller to be used on subsequent PDS requests.

Build and test your proxy Web service and then you are ready to move on to the next step of using this Web service from your Pocket PC application.

Adding Web Services

Adding your proxy Web service to your Pocket PC application is simple. You can do this in Visual Studio by selecting Add Web Reference on the Project menu. The Add Web Reference dialog box allows you several ways to locate a Web service. Because you have just created the proxy Web service, you can simply enter the following URL and click Go.

http://server_name/ProjectTimesheetPDSProxy/WSTimesheetPDS.asmx

The Add Web Reference dialog box displays the two methods advertised by your proxy Web service. Rename the default, WebService1, to WSTimesheetPDS and click Add Reference. The Add Web Reference Wizard generates all the necessary files for you. Keep in mind that the WSTimesheetPDS Web service you just added is the proxy Web service, so you do not make direct SOAP requests to the Timesheet PDS. Instead, the proxy Web service delegates requests from your Pocket PC to Microsoft Project Server. The end result is transparent to the user, even if the indirection is slightly inefficient.

Project Timesheet Forms

With the proxy Web service in place, you are ready to use its service and construct the logic to download your timesheet data. Before you do that, however, you should think about how the timesheet data is displayed. Take a moment to study the Timesheet view in Microsoft Project Web Access. The nature of the Pocket PC can create user interface design challenges in both display and usage. Because of the limited screen space, be careful to ensure that the user is not forced to constantly scroll. Likewise, you should consider how you would like to capture data inputs, such as task effort performed.

In this section, you create a ListView user interface element that resides in the existing frmMain form. In this ListView control, a column header should be defined that displays the name for each column, and several properties must be specified that govern the usage behavior, as well as provide feedback for changed data.

To create a ListView control

  1. In the Solution Explorer view, double-click frmMain.cs to display the Form Designer view.
  2. On the View menu, click Toolbox.
  3. Click and drag a ListView control from the Toolbox to frmMain.
  4. Right-click on the ListView control and click Properties.
  5. Set FullRowSelect to True.
  6. Set View to Details.
  7. Under the Behavior section, click (Collection) for the Columns field, and click the ellipsis () button.
  8. Add each column as indicated in the Mobile Timesheet application.
  9. Under the Design section, type lstTasks for the (Name) property.
  10. Set Location to 4,4.
  11. Set Size to 232,260.

You now need to define a behavior for when the user selects a list row. Returning to the Property view for lstTasks, locate the Events icon (Aa164307.odc_prpocketpctimesheet_fig1(en-us,office.10).gif) on the toolbar. If you hover over this icon with your mouse, the ToolTip should display "Events." If you click on this icon, a Behavior section should appear. The only two behaviors available for the ListView control are ItemCheck and SelectedIndexChanged. The Timesheet view does not use any check box controls, so the ItemCheck behavior is ignored. In-place editing for row items would be ideal for changing task work efforts, but this support is not directly available. This leaves the SelectedIndexChanged behavior as the only option with which to capture a user action on the list row. As its name implies, the SelectedIndexChanged event broadcasts only when the user selects a row other than the currently selected row. So, if there is no selected row to begin with, a row selection triggers the event to broadcast. However, clicking on the same selected row does not trigger the event. Keep this constraint in mind, as you need a workaround to allow the user to select the same row repeatedly. This topic is discussed further in the "Update Timesheet Data" section.

To define a ListView behavior

  1. Activate the Properties view for lstTasks, and click the Events icon.
  2. Under the Behavior section, type lstTasks_SelectedIndexChanged next to the SelectedIndexChanged field.

To complete your specification for the ListView control, you must define an ImageList control to be associated with it. The only reason this image control exists is to provide the user some visual feedback when a particular row changes. Because the .NET Compact Framework does not currently support any font attributes, displaying an icon is a good alternative for indicating changed data. Binding an ImageList control requires first creating the images. You can create a simple image in a drawing program, such as Microsoft Paint, and save the file as a bitmap, jpeg, gif, or icon. The image dimension should be 16×16 pixels.

To create and bind an ImageList control

  1. While still in the form design view for frmMain.cs, on the View menu, click Toolbox.
  2. Click and drag an ImageList control from Toolbox to frmMain.
  3. Right-click imageList1, displayed on the bottom pane of the form design view, and click Properties.
  4. Under the Design section for (Name) field, type imageListSmall.
  5. Under the Appearance section, click the **. . . ** button in the (Collection) field.
  6. In the Image Collection Editor dialog box, click Add.
  7. Select the image file that you have just saved, and click OK.
  8. C the Properties view for lstTasks.
  9. Under the Behavior section, point to the drop-down list next to SmallImageList and click imageListSmall.

When you close the Form Designer view, all the necessary code is generated for you. This includes the new private function lstTasks_SelectedIndexChanged, along with image list association. Take a moment to study the code listed in the region named Windows Form Designer generated code in frmMain.cs.

Logging on to Microsoft Project Server

Before you can access timesheet data, you must log on to the server running Microsoft Project Server. Because you have added the proxy Web service to assist you to log on, all you need now is to get the user name and password from the user. To help you do this, the Mobile Timesheet application includes a modal dialog with two text entries to capture the logon credentials for authentication.

In Visual Studio .NET 2003, you can add a new form to a project by selecting the Project menu and clicking Add Windows Form. This displays the Add New Item dialog box, where you can accept the defaults or create a new item. Use the form in frmLogin.cs, included in the Mobile Timesheet application, as a guide to create your form accordingly.

Once you have the ability to capture user credentials, you can create an instance of a proxy Web service class WSProjectTimesheet.WSTimesheetPDS, and log on by calling LoginToProjectServer with the user credentials. The sUserName and sPassword values should be the ones you obtained from the Login form.

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

The result of logon is returned as a string. If the logon is successful, the returned string is essentially a session identifier to be used for all subsequent PDS calls. If the logon fails, an empty string is returned. You should declare a string variable sCookie in your frmMain to help you manage the connected state with Microsoft Project Server. Whenever the user chooses to download or update the timesheet data, you can use the sCookie variable to detect whether the user needs to log on to Microsoft Project Server.

Retrieve Timesheet Data

After you have successfully logged on to the server running Microsoft Project Server, you can issue the AssignmentsGet PDS method to retrieve your timesheet data. Recall that you have already defined a Download menu item for the user to initiate the download process. Make sure you have declared an event handler for this menu item's Click event.

To create a menu item click event handler:

  1. Select form design view for frmMain.cs, click the View menu, and click Toolbox.
  2. On the Main menu, right-click the Download menu and click Properties.
  3. Click the Event icon, and enter menuDownload_Click next to the Click event.

The form designer creates the private function menuDownload_Click. This is where you should place the logic to download the timesheet data. As stated in the previous section, you should use the sCookie variable to check if the user needs to first perform a logon. Assuming the user has successfully gained access to Microsoft Project Server or is already authenticated, you now have all the information needed to retrieve timesheet data. Using the same proxy Web service for logon to Microsoft Project Server, call the PdsRequest method to retrieve the timesheet data for the authenticated user.

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

The returned string should contain XML-formatted data, as discussed in the "Project Timesheet" section. One of the easiest ways to access this data is to use the DataSet class offered in ADO.NET. The flexibility of the DataSet class is unmatched. One of its chief advantages is the ability to build tables with row and column objects from an XML-formatted string. This allows you to work with typed class objects, rather than parsing the string or using the XML DOM. Because this DataSet object is your interface for accessing and changing the timesheet data, you should declare a variable dsTimesheet of type DataSet in frmMain. Use the ReadXml method to load your DataSet object.

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

Note that there are three overloaded methods to ReadXml. The one used above accepts a derived class of XmlReader. This method defaults the XmlReadMode to Auto. The result of this method is simple and elegant, since it attempts to infer a schema, if one is missing. You will find the dsTimesheet dataset contains several tables that you can query for schema, as well as for data. The primary table you are working with is the Assignment table. This table contains columns that reflect the task properties. Take a moment to explore the objects and collections available to you in dsTimesheet.

Because you also want to allow the user to make updates to the timesheet, you must mark the modified tasks to determine which tasks have changed. This reduces the amount of uploaded data, sending only the changed tasks. The easiest way to track changed tasks is to add a Changed column to the Assignment table. You should also set the default for Changed to 0 for the downloaded tasks.

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;
}

Render Timesheet Data

Now that you have designed your form, specified a list view, and retrieved the timesheet data, you are ready to display the timesheet data. Because of the limited screen space on a Pocket PC, you should think about organizing the tasks list in a more manageable way. This is where the Project menu that you have specified comes in handy. Recall that each task listed in the timesheet data also contains a ProjectName property. You can simply group the tasks by their project name and display only those tasks for a selected project.

To extract all distinct project names from the task list, you must iterate through all tasks and perform name comparisons manually. This is because the DataTable.Select method does not support a DISTINCT filter, as in Transact-SQL, used in Microsoft SQL Server. For each distinct project name that you have retrieved, add a new menu item corresponding to that project to the Project menu. As you build the Project menu, remember also to create an event handler for the menu Click event. The code below specifies a private method ShowProject to receive the Click event for each project menu item.

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();

As the user selects a different project from the Project menu, you want to refresh the timesheet list to display the tasks for the selected project. The ShowProject method event handler should first remove all existing list rows from the list view, and then add the tasks belonging to the selected project. The projectName variable below is equivalent to the selected menu item's text.

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);            
}

The final step is to show whether a task has been changed. Because you have already specified an image list for the list view control, you can set each list row to default to show no image with the statement ListViewItem.ImageIndex = -1. The ImageList is a zero-based collection control. An index of 0 means you want the list row to display the first image in the collection. Likewise, an index of -1 indicates that no image should be displayed.

Working Offline

Typically, a Pocket PC is used in an offline mode. Battery life and available network connection are generally cited as the primary reasons for not supporting the always-on mode. The nature of a Pocket PC is to have the freedom not to be tethered to the office, but still have the majority of productivity tools with you. To achieve this goal with your mobile timesheet application, you must preserve the changes to the timesheet on the Pocket PC.

The DataSet class again offers a simple solution for writing the timesheet data to a file. Because all timesheet data is stored and tracked in the dsTimesheet object, you can use the WriteXml method to flush all data to a file. The WriteXml method is overloaded with two variations. For simplicity, you can choose to write to a file by specifying a full path, including the file name. You can also use the System.Reflection class to determine where your Mobile Timesheet application resides, and write your data file to the same location.

string sTimesheetFile = System.Reflection.Assembly

.GetExecutingAssembly().GetName()

.CodeBase.Replace("MobileTimesheet.exe", "Timesheet.xml"); 


dsTimesheet.WriteXml(sTimesheetFile); 

Once the data is written to a file, you can use any text editor to view it. Likewise, you can reload your dsTimesheet dataset when you restart the application by using the ReadXml method. By providing the same file path, sTimesheetFile, you can populate a dataset just as easily.

Update Timesheet Data

In the "Project Timesheet Forms" section, you learned how to add an event handler for the ListView control. The event handler method lstTasks_SelectedIndexChanged allows you to specify what happens when the user selects a list row. Because this event is triggered only when the selection of list row changes, you need to clear the selection after you process the event to allow the user to select the same row again. You can do this by setting ListViewItem.Selected = False. The primary use of the SelectedIndexChanged event is to activate an input form that allows the user to edit the amount of work completed for a selected task. Recalling that each task has an identifier UID, you can use ListView.SelectedIndices to index the selected row in the Assignment table and retrieve the identifier through DataRow["UID"].

Just as you have created an input form to capture user credentials, you should create a task edit form to capture the changed values. Again, using the downloaded code as a guide, you should allow for changes to the ActualWork, RemainingWork, and PercentWorkCompleted values. Note that these three fields are all anchored by the Work field, and changes to any one field affect the values of the remaining fields. Once you have completed this form, you can display it when the user clicks on a list row. If the user commits changes to a task, you must update the values in dsTimesheet to reflect the changed data. Also, you should update ListViewItem.ImageIndex = 0 to indicate that a particular task has been changed.

As soon as you have detected a changed task, whether through the Task Edit form or by loading the previously saved timesheet, you should add an Upload menu item to the Main menu. Just as you have added an event handler for the Download menu, create an event handler for the Upload menu. Keep in mind that you should check for the existence of the Upload menu item before creating it and specifying the event handler. Examine the AddMenuUpload method in the accompanying source code.

The existence of the Upload menu item is also a good indicator for changed timesheet data. In fact, when the user chooses to download his timesheet, you should provide a warning that existing timesheet data has been changed, and ask whether an upload should be performed first. You can check for the Upload menu item by using the Contains method in MenuItem.MenuItems. Before you perform the timesheet upload, you should also check if the user is logged on to Microsoft Project Server. This should be the same check that you make when downloading timesheet data. Use the sCookie variable you created earlier to determine whether the user is authenticated.

Referring back to the "Project Timesheet" section, the AssignmentsSave and AssignmentsProjectManagerUpdate PDS methods show the exact format you need to construct to successfully update the changed tasks. Because the AssignmentsSave and AssignmentsProjectManagerUpdate methods updates every task you indicate in the XML content, you should only send tasks that are marked "Changed = 1." By iterating through each row in the Assignment table, you can build the update XML strings by using the StringBuilder class.

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());

Once again, use the proxy Web service WSProjectTimesheet to send the XML string you build to update the timesheet data on Microsoft Project Server. Note that the PdsRequest method is same one you used to retrieve timesheet data. This time, however, you are sending an XML string that directs the Timesheet PDS to change a particular user's task data.

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

After you have successfully uploaded timesheet data, you should reset the Changed state for all tasks and remove the Upload menu item. Likewise, you should reset the ImageIndex to reflect unchanged tasks in the list view.

Conclusion

This article provides an introduction to bringing Microsoft Project data to Pocket PC devices. With further exploration and customization of PDS Extensions, you can easily make enhancements of your own, including tracking issues, as well as viewing task changes submitted by resources.

References

Following is a summary of the Microsoft and MSDN references in this article.