Step by Step: Build a Mobile Book Catalog with Visual Studio .NET 2003 for Pocket PC

 

Microsoft Corporation

February 2005

Applies to:
   Microsoft Visual Studio .NET 2003
   Microsoft .NET Compact Framework version 1.0
   Microsoft ActiveSync version 3.5
   ASP.NET version 1.1
   Microsoft Visual C#
   Microsoft Visual Basic .NET
   Microsoft Windows Powered Pocket PC 2002
   Windows Mobile-based Pocket PCs

Summary: The objective of this exercise is for you to learn how to use Visual Studio .NET 2003 to develop applications for Pocket PCs that use a Web service while both in online and offline states. (32 printed pages)

Download Building a Mobile Book Catalog with Visual Studio .NET 2003.msi from the Microsoft Download Center.

Contents

Introduction
Part 1: Creating a Windows Forms User Interface
Part 2: Consuming a Web Service
Part 3: Accessing the Platform API for the Device
Part 4: Handling the Offline Scenario
Summary
Appendix A: Using .NET Compact Framework Version 1.0 SP2
Appendix B: Installing the Microsoft Loopback Adapter
Appendix C: Inspecting a Web Service
Appendix D: Setting up the BookCatalogWS Web Service on the Development Computer

To complete this exercise, you will need:

  • Windows 2000 or Windows XP
  • Microsoft .NET Framework version 1.1
  • Microsoft .NET Compact Framework version 1.0 (If your computer is using .NET Compact Framework version 1.0 Service Pack 2 (SP2), please see Appendix A.)
  • Microsoft Visual C# .NET
  • Pocket PC 2003 SDK
  • Pocket PC 2003 Emulator
  • Pocket PC device (Part 4 of this exercise involves building offline functionality, which cannot be tested on an emulator.)
  • BookCatalogWS Web Service
  • Internet connection (If your computer does not have an active network connection, please see Appendices B and D.)

Important You will use BookCatalogWS in these exercises. If you do not have access to the Internet or cannot access this Web service for some other reason, you can setup the BookCatalogWS on your development computer instead. Follow the instructions in Appendix D.

Note For this exercise to work, your computer cannot be RASed in to the Microsoft network.

Introduction

In this exercise, you will become familiar with developing applications for mobile devices, such as Pocket PCs, by using Microsoft Visual Studio .NET 2003.

First, you will use the Microsoft Visual Studio .NET Integrated Development Environment (IDE) to create a Microsoft Windows form.

In the subsequent parts of this exercise, you will enhance the application to communicate with a Web service to retrieve a dataset containing a catalogue of products, to access the platform API for the device, to handle an offline scenario, and to inspect a Web service.

Part 1: Creating a Windows Forms User Interface

In this part of the exercise, you will create a Windows Form using Microsoft Visual C# or Microsoft Visual Basic .NET.

Some illustrations in this part of the exercise are thumbnails. You can click the thumbnails for larger images.

Creating a Windows Form Using Visual C# or Visual Basic .NET

In this task, you will create a smart device application project, add controls to it, set image properties, and run the application on the Pocket PC emulator.

To create the smart device application project

  1. Create a folder on drive C, and then rename this folder Labs.
  2. Copy the NetCFBookCatalogSolution zipped file from the download sample, and then paste it into the Labs folder on drive C.
  3. Extract the files from this zipped file in the Labs folder on drive C.
  4. Start Microsoft Visual Studio .NET 2003.
  5. On the File menu, point to New, and then click Project.
  6. In the project types pane, choose Visual C# Projects or Visual Basic Projects.
  7. In the templates pane, click Smart Device Application.
  8. In the Name box, type BookCatalogApp, and then choose a location for your project.
  9. Click OK to start the Smart Device Application Wizard.
  10. In the Platform list, choose Pocket PC.
  11. In the Project Type list, click Windows Application.
  12. Click OK to create the new project.

Note Visual Studio .NET creates the BookCatalogApp project in the BookCatalogApp solution. A Windows Form, called Form1, is automatically added to the project. It appears in the Windows Forms designer in the main window of Visual Studio .NET 2003.

To add controls to Form1

  1. Select Form1 in the Windows Forms designer. Form1's properties are displayed in the Properties window.

  2. In the Properties window in the Text box, type Book Catalog.

  3. On the View menu, click Toolbox.

  4. In the Toolbox, drag a Label control from the Device Controls tab onto the upper left of the form.

  5. Set the following properties for the Label:

    • Set the Text property to Mobile Book Catalog.
    • Set the Font property to Arial, 10pt, style=Bold.
  6. In the designer, drag the right anchor point to resize the label's width so that all of the text is displayed.

  7. In the Toolbox, drag a Button control from the Device Controls tab to the right of the label.

  8. Set the Button Text property to Get Items.

  9. In the Toolbox, drag a PictureBox control from the Device Controls tab to the lower left of the form.

  10. Set the PictureBox Size property to 83, 140.

  11. Reposition the PictureBox so that it sits inside the lower left of the form.

  12. In the Toolbox, drag a TextBox control from the Device Controls tab onto the lower right of the form.

  13. Set the following properties for the TextBox:

    • Set the Readonly property to True.
    • Set the Multiline property to True.
    • Set the ScrollBars property to Vertical.
    • Set the Font property to Arial, 9pt.
    • Set the Text property to Welcome to the Mobile Book Catalog! Click the "Get Items" button to download the catalog.
  14. Resize the TextBox so that it is the same height as the PictureBox and covers the lower right of the form.

  15. In the Toolbox, drag a ListView control from the Device Controls tab onto the upper center of the form.

  16. Position the ListView control between the controls at the top of the form and those at the bottom, and then resize it to fill the remaining space on the form, as shown in the following illustration.

    Click here for larger image

To set the image properties

Note The Image property cannot be set from the designer in the beta release of the SDE; therefore it must be set in code.

  1. On the View menu, click Solution Explorer.

  2. In the Solution Explorer, right-click the BookCatalogApp project, point to Add on the shortcut menu, and then click Add Existing Item.

  3. At the bottom of the Add Existing Item dialog box, change Files of type to Image Files.

  4. Browse to the supplied \images folder, select logo.gif, and then click Open to add the file to the project.

  5. In the Solution Explorer, select logo.gif.

  6. In the Properties window, set the logo.gif Build Action property to Embedded Resource. This action embeds the file in the main project build output.

  7. In the Solution Explorer, right-click Form1, and then select View Code.

  8. Add the following references to the top of the page (according to the language you are using).

    'Visual Basic
    Imports System.Reflection
    Imports System.IO
    
    //C#
    // Add these after any existing 'using' statements
    using System.Reflection;
    using System.IO;
    
  9. Add a method named AddImageToPictureBox to load the logo image into the PictureBox.

  10. Add the following code inside the Form1 class (according to the language you are using).

    'Visual Basic:
    Private Sub AddImageToPictureBox()
       PictureBox1.Image = New  System.Drawing.Bitmap(Reflection.Assembly.GetExecutingAssembly(). _
              GetManifestResourceStream("BookCatalogApp.logo.gif"))
       PictureBox1.Size = PictureBox1.Image.Size
    End Sub
    
    
    //C#:
    private void AddImageToPictureBox() {
       this.pictureBox1.Image = 
          new System.Drawing.Bitmap(Assembly.GetExecutingAssembly().
              GetManifestResourceStream("BookCatalogApp.logo.gif"));
       this.pictureBox1.Size = pictureBox1.Image.Size;
    }
    
  11. In Designer view for Form1, double-click the background of the form. Do not click any of the other controls. The code view for Form1 appears, and the cursor is placed inside an empty event handler for the Form1_load event.

  12. In the event handler, add the call to AddImageToPictureBox, as shown in the following code.

     'Visual Basic:
    Private Sub Form1_Load(ByVal sender As Object, _
                           ByVal e As System.EventArgs) _
                           Handles MyBase.Load
        AddImageToPictureBox()
    End Sub
    
    
    
    //C#:
    private void Form1_Load(object sender, System.EventArgs e)
    {
        AddImageToPictureBox();
    }
    

To run the application

  1. On the File menu, click Save All.

  2. In the Device Extensions toolbar, choose the Pocket PC Emulator in the Deployment Device box, as shown in the following illustration.

Note You can also change the deployment device in the Device Extensions project property page. In Visual Studio .NET 2003, on the Tools menu, click Options (or you can make the changes in the Properties window of the project).

  1. Press CTRL+F5 to run the application.

Note As you perform this step, Visual Studio .NET 2003 displays the Deploy prompt dialog box. Click Deploy to continue.

You may notice deployment errors when deploying an application to the emulator if the emulator is not running. Visual Studio .NET 2003 displays an error prompt dialog box that shows deployment errors and asks whether to continue or cancel. These errors are due to a timing issue with the SDE Beta release because the emulator is still opening. If deployment errors occur, wait until the emulator has loaded, click Cancel, then press CTRL+F5 to deploy and run the application again.

A window is displayed, as shown in the following illustration.

Click here for larger image

  1. Close the form by clicking OK in the top-right corner of the form.

Note If you are you having problems, try doing the following:

  • Make sure your computer is not RASed in to the Microsoft network.
  • On the File menu, point to Open, and then click Project. Browse through the file system to the supplied \Exercise1 folder.
  • If you are completing this exercise in C#, open the C# folder, and then open the BookCatalogAppCS solution.
  • If you are completing this exercise in Visual Basic .NET, open the Visual Basic .NET folder, and then open the BookCatalogAppVB solution.

Part 2: Consuming a Web Service

In this part of the exercise, you do the following:

  • Add a Web reference to the project.
  • Retrieve data from the Web service.

Some illustrations in this part of the exercise are thumbnails. You can click the thumbnails for larger images.

Adding a Web Reference to Your Project

In this task, you will add a Web reference to your project and access the Web service.

To add a Web reference to your project

  1. In Visual Studio .NET 2003, right-click References in the Solution Explorer.
  2. Click Add Web Reference.
  3. In the Add Web Reference window in the Address box, type http://apps.gotdotnet.com/netcf/BookCatalogWS/Service1.asmx.

Note If you installed the BookCatalogWS Web service on your development computer, rather than the version at GotDotNet, then type http://<server name>/BookCatalogWS/Service1.asmx in the Address box. Use the name of your development computer for <server name>. Do not use the server name of localhost because the application will run on the smart device, which is a separate computer from your development computer.

  1. Press ENTER or click Go located to the right of the Address box. The Add Web Reference dialog box appears, as shown in the following illustration.

    Click here for larger image

  2. Click Add Reference.

  3. After the Web reference is added, in the Solution Explorer, expand the Web References folder.

  4. Right-click com.gotdotnet.apps, click Rename, and then change to BookCatalogWS, as shown in the following illustration.

    When you add a new Web reference, the Web reference is by default given a name based on the host where the Web service resides. It is good practice to give the Web service reference a useful name; otherwise, it can make your code look untidy and difficult to manage. You can rename a Web Reference in the Solution Explorer, as explained in the previous procedure, or you can type the required name in the Web Reference Name box in the Add Web Reference dialog box.

    When you add a Web reference to a project, Visual Studio .NET 2003 generates a proxy class that it adds to your project. This class encapsulates the logic required to access the Web service by means of HTTP. For your application to use the Web service, you need to make a simple method call to this class.

    At the end of this exercise, Appendix C: Inspecting a Web Service gives you an overview about how Web services work from the client perspective.

In the next procedures, you will build the logic that accesses the Web service and handles the response. You should review the procedures that you've followed thus far to prepare for the next procedures.

The Web service uses a database that installs as part of the Visual Studio .NET 2003 Samples, extracts some data, and loads it into an ADO.NET DataSet. It returns a DataSet to the application as an XML response by means of HTTP. The class you previously added to your application when you added a Web reference to this Web service parses the XML response and creates a local copy of the Dataset on the device for use in your application.

Later in this exercise, you will use the DataSet returned from the Web service to populate a ListBox control. You will populate the ListBox control by taking the DataTable contained within it and iterating through its DataRows. The application will then take a DataItem (the equivalent of a column in a row) from that specific DataRow for insertion into the ListBox control. Note that there are many columns returned but you will only use specific ones.

One of the columns that the Web service returns in the DataTable is a byte array type that represents an image associated with that DataRow, in this case, a picture of a book cover. When a user selects a particular DataRow from the ListBox control, the application will then look up the specific DataRow in the Dataset, take the byte array for the image from the respective DataItem, and then build a Bitmap to be displayed in a PictureBox control.

Toward the end of this exercise, you will add functionality to store the Dataset locally on the device so that users can access the Dataset when not connected to a network.

To access the Web service

  1. In the Solution Explorer, right-click Form1, and then select View Code.

  2. Add the following reference to the top of the file (in the appropriate language).

    'Visual Basic:
    Imports System.Net
    
    
    //C#:
    using System.Net;
    
  3. Add the following members to the class Form1 (in the appropriate language). This action creates an instance of your proxy class (BookCatalogWS.Service1), a Dataset, and a DataTable.

     'Visual Basic:
    Private BookCatalogDS As DataSet = New DataSet()
    Private BookCatalogTable As DataTable = New DataTable()
    Private ws As BookCatalogWS.Service1 = New BookCatalogWS.Service1()
    
    
    
    //C#:
    private DataSet BookCatalogDS;
    private DataTable BookCatalogTable;
    private BookCatalogWS.Service1 ws = new BookCatalogWS.Service1();
    
  4. In the Solution Explorer, right-click Form1, and then select View Designer.

  5. Double-click Get Items to create an empty event handler for the Click event.

  6. Call GetItems by adding the following code.

     'Visual Basic:
    Private Sub Button1_Click(ByVal sender As System.Object, _
                              ByVal e As System.EventArgs) _
                              Handles Button1.Click
       Try
          BookCatalogDS = ws.GetItems()
          BookCatalogTable = BookCatalogDS.Tables("Titles")
          AddDataToListView()
       Catch we As WebException
          MessageBox.Show("Unable to connect. Error: " & we.Message, 
             "Connection Failed")
       End Try
    End Sub
    
    
    
    //C#:
    private void button1_Click(object sender, System.EventArgs e) {
       try {
          BookCatalogDS = ws.GetItems();
          BookCatalogTable = BookCatalogDS.Tables["Titles"];
          AddDataToListView();
       }
       catch (WebException we) {
          MessageBox.Show("Unable to connect. Error: " + we.Message, 
             "Connection Failed");
       }
    }
    

Note If you have primarily used Visual Basic in the past, you may notice the usage of MessageBox.Show instead of MsgBox. The MessageBox class is a standard .NET class accessible from any language. In previous versions of Visual Basic, MsgBox was a language-specific function for creating a message dialog box. Now you can create a message dialog box consistently across all .NET languages.

Retrieving Data from the Web Service

In this task, you will load the data into the ListView control and show descriptions and images of selected data.

To load the data into the ListView control

  • Add a method named AddDataToListView to load the data (in the appropriate language).

     'Visual Basic:
    Private Sub AddDataToListView()
       Dim row As DataRow
       Dim item As ListViewItem
       ListView1.Clear()
       ListView1.Columns.Add("Title", ListView1.Width - 60, HorizontalAlignment.Left)
       ListView1.Columns.Add("Price", 45, HorizontalAlignment.Right)
       ListView1.View = View.Details
    
       For Each row In BookCatalogTable.Rows
          item = New ListViewItem(DirectCast(row("title"), String))
          If (Not row("price") Is DBNull.Value) Then
             item.SubItems.Add(String.Format("{0:F2}", DirectCast(row("price"),
                Decimal)))
          End If
          ListView1.Items.Add(item)
       Next row
       TextBox1.Text = "Click on a book title to see an image" + _
           " of the book cover and a description."
    End Sub
    
    
    //C#:
    private void AddDataToListView() {            
       ListViewItem item;
       listView1.Clear();
       listView1.Columns.Add("Title",listView1.Width – 60,HorizontalAlignment.Left);
       listView1.Columns.Add("Price",45,HorizontalAlignment.Right);
       listView1.View = View.Details;            
    
       foreach(DataRow row in BookCatalogTable.Rows) {
          item = new ListViewItem(row["title"].ToString());
          if(row["price"] != DBNull.Value) {
             item.SubItems.Add(String.Format("{0:F2}",(decimal)row["price"]));
          }
          listView1.Items.Add(item);   
       }
       textBox1.Text = "Click on a book title to see an image" +
          " of the book cover and a description.";
    }
    

To show the description and image of the selected book

  1. In the Solution Explorer, right-click Form1, and then click View Designer.

  2. Double-click ListView1 to create an empty event handler for the SelectedIndexChanged event.

  3. In this event handler, ensure that the PictureBox control is updated with the correct image from the dataset by constructing a MemoryStream from the byte array that is stored in the dataset for that image. The MemoryStream is then used to construct a Bitmap object that the PictureBox can display as an image.

  4. Add the following code to the SelectedIndexChanged event handler method (in the appropriate language).

    'Visual Basic:
    Private Sub ListView1_SelectedIndexChanged(ByVal sender As System.Object, _
                                               ByVal e As System.EventArgs) _
                                               Handles ListView1.SelectedIndexChanged
    Dim row As DataRow
    If (ListView1.SelectedIndices.Count > 0) Then
          row = BookCatalogTable.Rows(ListView1.SelectedIndices(0))
          TextBox1.Text = "Description: " & vbNewLine & row("notes").ToString() 
          Try
             PictureBox1.Image = New Bitmap(New MemoryStream(DirectCast(row("Image"),
                Byte())))
          Catch ne As InvalidCastException
             MessageBox.Show("Could not load image. Error: " & ne.Message)
          End Try
       End If
    End Sub
    
    
    
    //C#:
    private void listView1_SelectedIndexChanged(object sender, System.EventArgs e) {
       DataRow row;
       if (listView1.SelectedIndices.Count > 0) {
          row = BookCatalogTable.Rows[listView1.SelectedIndices[0]];
          textBox1.Text = "Description:\r\n" + row["notes"].ToString();
          try {
             pictureBox1.Image = new Bitmap(new MemoryStream((byte[])row["Image"]));            
          }
          catch(System.InvalidCastException ne) {
             MessageBox.Show("Could not load image. Error: " + ne.Message);
          }
       }
    }
    
  5. Press CTRL+F5 to compile and run the application.

  6. Press Get Items to test the call from the client to the Web service, and then observe the result. Be patient after clicking the button because it takes time to load the dataset from the Web service the first time. The emulator screen should look like the following illustration.

    Click here for larger image

    Note If you are you having problems, try doing the following:

    • Make sure that your computer is not RASed in to the Microsoft network.
    • You may need to configure it for Internet connectivity before the application functions properly. Click Start, point to Settings, and then click Connections. Set your automatic settings to Work Settings. Also, make sure that all of the proxy connections under Work Settings are appropriately set.
    • On the File menu, point to Open, and then click Project. Browse through the file system to the \NetCFBookCatalogSolution\Exercise2 folder.
    • If you are completing this exercise in C#, open the C# folder, and then open the solution named BookCatalogAppCS.
    • If you are completing this exercise in Visual Basic .NET, open the Visual Basic .NET folder, and then open the BookCatalogAppVB solution.
    • If you installed the BookCatalogWS Web service on your development computer, rather than the version at GotDotNet, you must point the Web service reference to the version on your computer.

To point the Web service reference to the version on your computer

  1. In the Solution Explorer, expand Web References, and then select BookCatalogWS.
  2. In the Properties window, change the Web Reference address property to http://<server name>/BookCatalogWS/Service1.asmx (Use the name of the computer where you installed the Web service.) Do not use the server name of localhost because the application will run on the smart device, which is a separate computer from your development computer.
  3. Press the ENTER key, and then press CTRL, SHIFT+B to build the project before continuing.

Part 3: Accessing the Platform API for the Device

This part of the exercise, you will add a wait cursor for visual feedback.

Adding a Wait Cursor for Visual Feedback

In this task, you will use Platform Invoke Services (P/Invoke) to call an unmanaged DLL function that will add visual feedback to your application in the form of a wait cursor. This process can be summarized as follows:

  • Import Interop services
  • Declare the value to be defined as the wait cursor
  • Declare the functions that define usage of the wait cursor
  • Wrap the functionality to make using the wait cursor functionality easy

To add a wait cursor to your application

  1. In the Solution Explorer, right-click Form1, and then click View Code.

  2. Add the following reference to the top of the file (in the appropriate language).

     'Visual Basic:
    Imports System.Runtime.InteropServices
    
    //C#:
    using System.Runtime.InteropServices;
    
  3. Add the following declaration to the class Form1 to define the cursor type:

     'Visual Basic:
    Private hourGlassCursorID As Integer = 32514
    
    //C#:
    private static int hourGlassCursorID = 32514;
    
  4. Declare the unmanaged DLL function to tell the compiler that the implementation comes from coredll.dll. In Visual Basic, use the Lib attribute. In C#, use the DllImport attribute.

     'Visual Basic:
    Declare Function LoadCursor Lib "coredll.dll" (ByVal zeroValue As Integer, _ 
                                                   ByVal cursorID As Integer) _
                                                   As Integer
    Declare Function SetCursor Lib "coredll.dll" (ByVal cursorHandle As Integer) _
                                                  As Integer
    
    
    
    //C#:
    [DllImport("coredll.dll")]
    public static extern int LoadCursor (int zeroValue, int cursorID);
    [DllImport("coredll.dll")]
    public static extern int SetCursor(int cursorHandle);
    
  5. Add the following method to the Form1 class to enable the display of the wait cursor:

     'Visual Basic:
    Public Sub ShowWaitCursor(ByVal value As Boolean)
       Dim cursorHandle As Integer = 0
       If value Then
          cursorHandle = LoadCursor(0, hourGlassCursorID)
       End If
       SetCursor(cursorHandle)
    End Sub
    
    
    
    //C#:
    private static void ShowWaitCursor (bool value) {
       SetCursor (value ? LoadCursor(0, hourGlassCursorID) : 0);
    }
    
  6. Add the code to turn the wait cursor on and off at the appropriate times. For example, Button1_Click may now look like the following.

     'Visual Basic:
    Private Sub Button1_Click(ByVal sender As System.Object, _
                              ByVal e As System.EventArgs) _
                              Handles Button1.Click
       ShowWaitCursor(True)
       Try
          BookCatalogDS = ws.GetItems()
          BookCatalogTable = BookCatalogDS.Tables("Titles")
          AddDataToListView()
       Catch we As WebException
          MessageBox.Show("Unable to connect. Error: " & we.Message, 
             "Connection Failed")
       End Try
       ShowWaitCursor(False)
    End Sub
    
    
    
    //C#:
    private void button1_Click(object sender, System.EventArgs e) {
       ShowWaitCursor(true);
       try {
          BookCatalogDS = ws.GetItems();
          BookCatalogTable = BookCatalogDS.Tables["Titles"];
          AddDataToListView();
       }
       catch (WebException we) {
          MessageBox.Show("Unable to connect. Error: " + we.Message, 
             "Connection Failed");
       }
       ShowWaitCursor(false);
    }
    
  7. Press CTRL+F5 to compile and run your application.

  8. On the emulator, click Get Items to test the cursor functionality.

  9. Close the application in the emulator.

Note It is also possible and easier to use the .NET Compact Framework class library to set the wait cursor. You can search for Cursor.Current in the online help for more details. To demonstrate platform invocation, this walkthough does not use the Cursor.Current approach.

Note You should now see that when Get Items is clicked, a wait cursor is displayed on the emulator. This ensures that the user is aware that the program is working and has not locked up.

On the emulator, the cursor displays as an hour glass while the wait cursor is active. If you are testing with a real Pocket PC device, the wait cursor appears as a circling multi-color graphic in the center of the screen.

Using similar methods, you can invoke other features from the Platform API such as accessing the registry and using the hardware buttons on the device within your application.

Note If you are having problems, try doing the following:

  • On the File menu, point to Open, and then click Project. Browse through the file system to the \NetCFBookCatalogSolution\Exercise3 folder.
  • If you are completing this exercise in C#, open the C# folder, and then open the solution named BookCatalogAppCS.
  • If you are completing this exercise in Visual Basic .NET, open the VB folder, and then open the BookCatalogAppVB solution.
  • If you installed the BookCatalogWS Web service on your development computer rather than the version at GotDotNet, you must now point the Web Service reference to the version on your computer.

To point the Web service reference to the version on your computer

  1. In the Solution Explorer, expand Web References, and then select BookCatalogWS.
  2. Open the BookCatalogWS properties, and then change the Web Reference address property to http://<server name>/BookCatalogWS/Service1.asmx. For <server name>, use the name of the computer where you installed the Web service. Do not use the server name of localhost because the application will run on the smart device, which is a separate computer from your development computer.
  3. Press ENTER, and then press CTRL, SHIFT+B to build the project before continuing.

Part 4: Handling the Offline Scenario

In this part of the exercise, you will perform the following tasks:

  • Saving the dataset to a file
  • Loading the dataset from the file

Saving the Dataset to a File

In this task, you will save the dataset retrieved from the Web Service so it can be viewed offline. The dataset will be saved in an XML file that is stored on the device whenever the application is closed.

To save the dataset to a file

  1. In the Solution Explorer, right-click Form1, and then select View Code.

  2. Add the following reference (in the appropriate language).

     'Visual Basic:
    Imports System.Xml
    
    //C#:
    using System.Xml;
    
  3. Add the following declaration to the class Form1 (C# only).

    //C#:
    private static string DataDirectory = 
        @"\Program Files\BookCatalogApp\Data\";
    private static string DataFile = 
        @"\Program Files\BookCatalogApp\Data\Catalog.xml";
    
  4. Add the following code to create the Closing event for Form1 (in the appropriate code).

    'Visual Basic:
    Private Sub Form1_Closing(ByVal sender As Object, _
                              ByVal e As System.ComponentModel.CancelEventArgs) _
                              Handles MyBase.Closing
       Dim Writer As XmlWriter
       Dim CatalogFile As FileInfo
       Dim dir As DirectoryInfo
    
       'Create application directory if it doesn't exist
       dir = New DirectoryInfo("\Program Files\MobileBookCatalogVB\Data")
       If (Not dir.Exists) Then
          dir.Create()
       End If
    
       'Delete file if it exists 
       CatalogFile = New FileInfo( _
           "\Program Files\MobileBookCatalogVB\Data\Catalog.xml")
       If (CatalogFile.Exists) Then
          CatalogFile.Delete()
       End If
    
       'Save BookCatalogTable if it has info in it 
       If (Not (BookCatalogDS.Tables.Count = 0)) Then
          Writer = New XmlTextWriter( _
            "\Program Files\MobileBookCatalogVB\Data\Catalog.xml", _
             System.Text.Encoding.Unicode)
          BookCatalogDS.WriteXml(Writer, XmlWriteMode.WriteSchema)
          Writer.Close()
       End If
    End Sub
    
    
    
    //C#:
    private void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e) {
       DirectoryInfo dir;
       FileInfo CatalogFile;
       XmlWriter Writer;
    
       //Create application directory if it doesn't exist
       dir = new DirectoryInfo(DataDirectory);
       if (!dir.Exists) {
          dir.Create();
       }
    
       //Delete file if it exists
       CatalogFile = new FileInfo(DataFile);
       if (CatalogFile.Exists) {
          CatalogFile.Delete();
       }
    
       //Save BookCatalogTable if it has info in it
       if (BookCatalogDS.Tables.Count != 0) {
          Writer = new XmlTextWriter(DataFile, System.Text.Encoding.Unicode);
          BookCatalogDS.WriteXml(Writer,XmlWriteMode.WriteSchema);
          Writer.Close();
       }
    }
    

Loading the Dataset from the File

In this task, you will load the dataset from the file. When you open the application again, it will load the dataset on the device from the XML file.

To load the dataset from the file

  1. Add the method LoadCatalogFromFile to load the dataset from the file (in the appropriate language).

     'Visual Basic:
    Private Sub LoadCatalogFromFile()
       Dim CatalogFile As New FileInfo("\Program
          Files\MobileBookCatalogVB\Data\Catalog.xml")
    
       If (CatalogFile.Exists) Then
          Try
             BookCatalogDS = New DataSet()
             BookCatalogDS.ReadXml("\Program
                Files\MobileBookCatalogVB\Data\Catalog.xml")
             Catch ex As Exception
                MessageBox.Show(ex.Message)
          End Try
    
          BookCatalogTable = BookCatalogDS.Tables("Titles")
          AddDataToListView()
       End If
    End Sub
    
    
    
    //C#:
    private void LoadCatalogFromFile() {            
       FileInfo CatalogFile = new FileInfo(DataFile);        
    
       if (CatalogFile.Exists) {
          try {
             BookCatalogDS = new DataSet();
             BookCatalogDS.ReadXml(DataFile);
             BookCatalogTable = BookCatalogDS.Tables["Titles"];
          }
          catch (Exception ex) {
             MessageBox.Show(ex.Message);
          }
          AddDataToListView();
       }
    }
    
  2. Add the call to LoadCatalogFromFile when the form is loaded (in the appropriate language).

     'Visual Basic:
    Private Sub Form1_Load(ByVal sender As Object, _
                           ByVal e As System.EventArgs) _
                           Handles MyBase.Load
       AddImageToPictureBox()
       LoadCatalogFromFile()
    End Sub
    
    
    
    //C#: 
    private void Form1_Load(object sender, System.EventArgs e)
            {
                AddImageToPictureBox();
                LoadCatalogFromFile();
            }
    
  3. Add the code to overwrite the dataset only if the Web service call is successful.

    You used the TempDS dataset because when you previously opened and closed the application in the Form_Closed event, the dataset that was collected was stored in a local file on the device.

    When the application is run the next time, the TempDS dataset is used as an intermediary dataset, which stores the data from the file in the applications Form_Load event until you tap Get Items again. This consequently loads a fresh dataset from the Web service.

    Using the intermediary dataset ensures that if you try to get a fresh dataset from the Web service and there is a failure, for example, the device is not connected to a network, then the dataset that was stored locally is not affected — you can still use the application with the data stored in TempDS.

  4. Add this code to the Button1_Click event.

    ' Visual Basic:
    Private Sub Button1_Click(ByVal sender As System.Object, _
                              ByVal e As System.EventArgs) _
                              Handles Button1.Click
       Dim TempDS As DataSet
       ShowWaitCursor(True)
       Try
          TempDS = ws.GetItems()
          BookCatalogDS = TempDS      
          BookCatalogTable = BookCatalogDS.Tables("Titles")
          AddDataToListView()
       Catch we As WebException
          MessageBox.Show("Unable to connect. Error: " & we.Message, 
             "Connection Failed")
       End Try
       ShowWaitCursor(False)
    End Sub
    
    
    
    // C#:
    private void button1_Click(object sender, System.EventArgs e) {
       DataSet TempDS = new DataSet();
       ShowWaitCursor(true);
       try {
          TempDS = ws.GetItems();
          BookCatalogDS = TempDS;      
          BookCatalogTable = BookCatalogDS.Tables["Titles"];
          AddDataToListView();
       }
       catch (WebException we) {
          MessageBox.Show("Unable to connect. Error: " + we.Message, 
             "Connection Failed");
       }
       ShowWaitCursor(false);
    }
    
  5. Connect and synchronize a Pocket PC device to your computer.

  6. Select the Pocket PC Device in the Deployment Device box on the Device Extensions toolbar.

  7. Press CTRL+F5 to compile and run your application.

  8. Tap Get Items to download the information from the Web site.

  9. Remove the device from cradle.

  10. Observe that the catalog data can be viewed without having a connection to the Web service.

  11. Close the form.

**Note   **If you are having problems, try doing the following:

  • On the File menu, point to Open, and then click Project. Browse through the file system to the \NetCFBookCatalogSolution\Exercise4 folder.
  • If you are completing this exercise in C#, open the C# folder, and then open the solution named BookCatalogAppCS.
  • If you are completing this exercise in Visual Basic .NET, open the VB folder, and then open the BookCatalogAppVB solution.
  • If you installed the BookCatalogWS Web service on your development computer, rather than the version at GotDotNet, you must now point the Web Service reference to the version on your computer.

To point the Web service reference to the version on your computer

  1. In the Solution Explorer, expand Web References, and then select BookCatalogWS.
  2. In the Properties window, change the Web Reference address property to http://<server name>/BookCatalogWS/Service1.asmx (Use the name of the computer where you installed the Web service.) Do not use the server name of localhost because the application will run on the smart device, which is a separate computer from your development computer.
  3. Press the ENTER key, and then press CTRL, SHIFT+B to build the project before continuing.

Summary

Congratulations! You have now completed this exercise. In this exercise, you performed the following tasks:

  • Created a Windows Forms user interface
  • Consumed a Web service
  • Accessed the platform API for the device
  • Handled the offline scenario

Appendix A: Using .NET Compact Framework Version 1.0 SP2

If your computer has Microsoft .NET Compact Framework version 1.0 SP2 installed, and you have not updated the netcf.core.ppc3.ARM.cab and netcf.core.ppc3.x86.cab files in .NET Compact Framework version 1.0, you need to update these files prior to beginning this exercise. The installation of SP2 does not automatically update these cab files for you.

To update the netcf.core.ppc3.ARM.cab and netcf.core.ppc3.x86.cab files in .NET Compact Framework version 1.0

  1. Open two instances of My Computer.
  2. In the first instance, navigate to C:\Program Files\Microsoft Visual Studio .NET 2003\CompactFrameworkSDK\v1.0.5000\Windows CE\wce300\arm.
  3. In the second instance, navigate to C:\Program Files\Microsoft .NET Compact Framework 1.0 SP2.
  4. Copy the netcf.core.ppc3.ARM.cab file from the second instance and paste it into the first instance.
  5. Click Yes to replace the existing file.
  6. Change the location of first instance of My Computer to C:\Program Files\Microsoft Visual Studio .NET 2003\CompactFrameworkSDK\v1.0.5000\Windows CE\wce300\x86.
  7. In the second instance, copy the netcf.core.ppc3.x86.cab file, and then paste it into the first instance.
  8. Click Yes to replace the existing file.

Appendix B: Installing the Microsoft Loopback Adapter

If your computer does not have an active network connection, you must install the Microsoft Loopback Adapter to simulate an active connection. The following steps assume that your computer is running Windows XP.

To add the adapter

  1. Open the Control Panel, and then click Add Hardware.
  2. In the Add Hardware Wizard, click Next until you see Is the hardware connected? Select Yes, I have already connected the hardware, and then click Next.
  3. In the Installed Hardware list, select Add a new hardware device, and then click Next.
  4. Select Install the hardware that I manually select from a list (Advanced), and then click Next.
  5. In the Common hardware types list, select Network Adapters, and then click Next.
  6. In the Manufacturer list, select Microsoft. In the Network Adapter list, select Microsoft Loopback Adapter, and then click Next.
  7. Continue to click Next through the Add Hardware Wizard as it installs the Microsoft Loopback Adapter.
  8. Restart the computer if prompted.

To test the connectivity of the emulator

  1. Open Pocket Internet Explorer on the emulator.
  2. If the address bar is not visible, click the View menu, and then click Address Bar.
  3. Type the address of the Web service used in Part 2 in the URL box: http://apps.gotdotnet.com/netcf/BookCatalogWS/Service1.asmx, and then click Go. If the Web service page loads correctly, the network connectivity on the emulator is working correctly.

Appendix C: Inspecting a Web Service

In this appendix, you will perform the following tasks:

  • Invoking a Web service
  • Investigating the Web Services Description Language (WSDL) file

Invoking a Web Service

In this task, you will inspect a Web service and observe how objects returned from the Web service are serialized as XML.

To invoke a Web service

  1. Open a Web browser window, and then type the following URL: http://apps.gotdotnet.com/netcf/BookCatalogWS/Service1.asmx.

  2. Click the GetItems link, and then click the Invoke button.

  3. Examine how the objects are serialized as XML.

      <?xml version="1.0" encoding="utf-8" ?> 
    - <DataSet xmlns="http://tempuri.org/">
      - <xs:schema id="NewDataSet"  xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
        - <xs:element name="NewDataSet" msdata:IsDataSet="true">
          - <xs:complexType>
            - <xs:choice maxOccurs="unbounded">
              - <xs:element name="Titles">
                - <xs:complexType>
                  - <xs:sequence>
                      <xs:element name="title_id" type="xs:string" minOccurs="0" />  
                      <xs:element name="title" type="xs:string" minOccurs="0" /> 
                      <xs:element name="type" type="xs:string" minOccurs="0" /> 
                      <xs:element name="pub_id" type="xs:string" minOccurs="0" /> 
                      <xs:element name="price" type="xs:decimal" minOccurs="0" /> 
                      <xs:element name="advance" type="xs:decimal" minOccurs="0" /> 
                      <xs:element name="royalty" type="xs:int" minOccurs="0" /> 
                      <xs:element name="ytd_sales" type="xs:int" minOccurs="0" /> 
                      <xs:element name="notes" type="xs:string" minOccurs="0" BV/> 
                      <xs:element name="pubdate" type="xs:dateTime" minOccurs="0" /> 
                      <xs:element name="Image" type="xs:base64Binary" minOccurs="0" /> 
                    </xs:sequence>
                  </xs:complexType>
                </xs:element>
              </xs:choice>
            </xs:complexType>
          </xs:element>
      </xs:schema>
    
  4. Notice the names and types of the data elements. You will use these later when populating the ListView control.

Examining the WSDL file

In this task you will examine the WSDL file that .NET provides for users of the service.

  1. Navigate directly to the WSDL page using the URL http://apps.gotdotnet.com/netcf/BookCatalogWS/Service1.asmx?wsdl.
  2. Spend a few minutes examining the WSDL file. Note that many definitions are repeated three times, one for SOAP, one for HTTP GET, and one for HTTP POST. These definitions describe how the Web service can be accessed using different protocols. SOAP is the protocol typically used by client applications to access a Web service, while the HTTP GET method is employed by the Web browser when calling the Web service (as was done in this exercise).
  3. Close the Web browser window.

Appendix D: Setting up the BookCatalogWS Web Service on the Development Computer

If you do not have access to the Internet or cannot access this Web service for some other reason, you can setup the BookCatalogWS on a development computer instead.

Prior to setting up the BookCatalogWS Web service, you must first install the Visual Studio .NET Samples (Quickstarts). The Web service uses one of the databases that is installed with the samples.

To install the Microsoft Visual Studio .NET samples

  1. Open Microsoft .NET Framework SDK – Samples and QuickStart Tutorials.
  2. Follow the instructions for installing and setting up the samples.

To create the BookCatalogWS Web service

  1. Open Microsoft Visual Studio .NET.
  2. On the File menu, point to New, and then click Project.
  3. In the Project Types pane, select Visual C# Projects.
  4. In the Templates pane, click ASP.NET Web Service.
  5. Type http://localhost/BookCatalogWS in the address field. If you want to install the Web Service on another computer, then specify a different host name other than localhost.
  6. Click OK. You should now see your new C# Web service project.

To add the Code files

  1. If the Solution Explorer is not visible, click the View menu, and then click Solution Explorer.
  2. In the Solution Explorer, right-click BookCatalogWS, click Add, and then click Add Existing Item.
  3. Navigate to the \NetCFBookCatalogSolution\Setup folder, and then select Service1.asmx and Service1.asmx.cs. If you do not see both files listed, then in the File Types drop-down list, select All Files, and then the files should appear. Click OK.
  4. A dialog box should appear that asks if you want to replace the existing files. Select Apply to all items, and then click Yes. The new files should appear.

To add the reference to System.Drawing

  1. In the Solution Explorer, right-click References, and then click Add Reference. The Add Reference dialog box should appear.
  2. By default, the Add Reference dialog box should display the list in the .NET tab. In that list, scroll down to the item called System.Drawing.dll.
  3. Select System.Drawing.dll, and then click Select. The Selected Components item should appear.
  4. Click OK. The BookCatalogWS Web service is now ready to be tested.

To test the BookCatalogWS Web service

  1. Press F5 to debug and deploy the application. The application should compile and deploy. A Web browser should open the Service1 Web page, as shown in the following illustration.

    Click here for larger image

  2. In the browser window, click the GetItems hyperlink. The Web browser opens a new Web page that shows you the operations that are available on the Web Service, and an option for testing the Web Service.

  3. Click Invoke to test the Web service. You should see a new browser window opening that is an invocation of the Web service. Inside the new window should be a collection of XML representing an XML Dataset returned.

  4. Close all of the browser windows.

  5. In Visual Studio .NET, click File, and then click Save All.

  6. Close Visual Studio .NET.