Pocket PC (General) Technical Articles
Northwind Pocket Analyze: Decision Support for Windows Mobile-based Smartphones
 

Christian Forsberg

business anyplace

March 2006

Applies to:
   Windows Mobile 2003–based Smartphones
   Microsoft Visual Studio .NET 2003
   Microsoft .NET Compact Framework version 1.0

Summary: Learn about mobile decision support and how to design and develop solutions for Windows Mobile 2003–based Smartphones using Visual Studio .NET and the .NET Compact Framework. The download code sample for this article implements a server XML Web service, a database, and a Smartphone client. (39 printed pages)


Download Northwind_Traders_Decision_Support_SP.msi from the Microsoft Download Center.

Contents

Introduction
Northwind Traders's Decision Support Business Process
Application Design
Data Analysis
Connection Aware
Screen Resolution Aware
Data Compression
Northwind Pocket Analyze Application Walkthrough
Code Walkthrough
Conclusion

Introduction

This article continues on the topics presented in these articles:

The first and second articles describe key elements about how to develop mobile field service applications. The third and fourth articles focus on developing mobile field sales applications. The fifth and sixth articles describe the design and implementation of mobile logistic solutions, and the seventh and eighth articles focus on solutions for supporting a transportation business process. The last article introduces the use of mobile devices as a data analysis tool and introduces a decision support process. It also covers a field sample application for supporting that process.

This article is about designing and developing a mobile decision support application that is based on the .NET Framework, the Windows Mobile platform for Smartphone, and the .NET Compact Framework. The sample solution addresses the needs of the fictitious company Northwind Traders from a decision support process and field data analysis points of view. From a technological point of view, the sample demonstrates how to implement an orientation-aware user interface, implement basic pivot tables, use GDI+ to do basic charting (the beginning of a line and bar chart custom control), use the hardware keys for user interface navigation, use compression in remote communication (XML Web service calls) and optimize local storage, make applications be connection aware, capture screen shots, and more.

Northwind Traders's Decision Support Business Process

As previous articles have described, the customers of Northwind Traders have vending machines that sell various products from Northwind Traders. As described in the article, >Northwind Pocket Analyze: Decision Support for Windows Mobile-based Pocket PCs, the decision makers at Northwind Traders wanted a data analysis solution that would make use of up-to-date data from the information infrastructure and would work without a network connection. The following are the steps of the business process that such a solution would support:

  1. Retrieve the data to analyze.
  2. Create a view of the data to analyze.
  3. Analyze the data as a table.
  4. Analyze the data as a chart.
  5. Report a decision using the table and chart.

That business process can be illustrated as shown in Figure 1.

Figure 1. Business process illustration

As shown in Figure 1, the main steps in the business process involve a number of sub-activities that function as main requirements for the new solution. Assuming this is a good way to define the new process, the next step would be to look at the design of the application.

Application Design

The article, Northwind Pocket Service: Field Service for Windows Mobile-based Pocket PCs, shows a good introduction to the architectural work in a mobile solution. The article, Northwind Pocket Inventory: Logistics for Windows Mobile-based Pocket PCs, describes the most important deliverables (artifacts) in the application's design. The design begins with the definitions of the use cases. Figure 2 shows the use cases for the sample application.

Figure 2. Use case model

Another very important artifact to create early in the design process is the dialog model and sample dialogs. Figure 3 illustrates the dialog model for the sample application.

Figure 3. Dialog model

The dialog model gives an overview of the dialogs (forms) that are included in the application, and the model also shows the navigation between these dialogs.

Figure 4 shows some sample dialogs.

Click here for larger image

Figure 4. Sample dialogs. Click the thumbnail for a larger image.

These dialog samples were drawn in a general drawing tool (in this case, Microsoft PowerPoint). Someone who is knowledgeable in user interface design should be involved in creating the dialogs. Visualizing the application's dialogs early in the process gives the users and other stakeholders an opportunity to understand how the application will look (and work). Changes are also very easy to make at this stage.

In the Northwind_Traders_Decision_Support_SP.msi, you can find all of the previous figures in a PowerPoint presentation that you can reuse when you create your own diagrams and dialogs.

Data Analysis

You can rapidly transform data that is stored in SQL Server and its Analysis Services combined with client tools like Microsoft Office and the Office Web Components into interactive Web pages for data analysis, as shown in Figure 5.

Click here for larger image

Figure 5. Sample Web page that uses Office Web Components. Click the thumbnail for a larger image.

Although these tools are not available to Smartphone users, this article's sample shows how you can add similar functionality—however basic—to an enterprise analysis application.

For more details about the data analysis tools, see the article, >Northwind Pocket Analyze: Decision Support for Windows Mobile-based Pocket PCs.

Connection Aware

Because communication cost is an important issue in most enterprise application scenarios, the need to optimize the use of that communication is critical. First, the communication should only take place when it is necessary, and second, when the communication needs to take place, it should be done in the most efficient way. This article discusses the latter topic in the Data Compression section.

To be sure that the communication takes place only when it is necessary, a solution needs to put the user in control of when communication occurs and needs to make data locally available to allow the application to function without the need of a network connection. With an option to force the application to retrieve data locally even though a network connection occurs (similar to the Work Offline option in Internet Explorer), the user controls when communication occurs.

If the user selects to work in online mode and there is a network connection available, the application retrieves the data from the server (as the red arrow that is marked with 1 in Figure 6 indicates). After each transfer, the fresh data is also stored locally (which you can think about as a local cache) to be available when the user needs it (as the red arrow marked with 2 in Figure 6 indicates). If the user selects to work in online mode and a network connection is not available, the application retrieves the data from the local storage (as the blue arrow marked with 3 in Figure 6 indicates). If the user selects to work in an offline mode, the application retrieves data from a local storage (as the blue arrow marked with 3 in Figure 6 indicates).

Figure 6. Data retrieval options

This is how the sample application accompanying this article is implemented to function independent of a network connection.

Screen Resolution Aware

The normal screen resolution of a Smartphone is 176 pixels (width) x 220 pixels (height). Most Smartphone applications are designed for this screen resolution. However, Windows Mobile 2003 Second Edition software for Smartphones also supports the resolution 240 x 320, also known as Quarter VGA (QVGA). Because there are Smartphones on the market that take advantage of this screen resolution, applications need to support the QVGA format as well.

The Code Walkthrough section reveals that it is not very difficult to implement screen-resolution awareness in a .NET Compact Framework application; therefore, there is no good excuse (except maybe time and cost) for excluding such support.

Data Compression

Developers can use data compression in enterprise applications for a number of reasons:

  • Reduce storage space.
  • Reduce communication time.
  • Reduce communication cost.
  • Increase performance.

Storage is a scarce resource on any mobile device, and anything that developers can do to reduce the space that an application requires is welcome. Although XML is an attractive standard to use due to its general acceptance and the support that is built into most development tools, the XML file format is far from space efficient because it is text based and includes a lot of extra information (like tag names). However, the XML format is very suitable for data compression, as shown in Figure 7.

Figure 7. Compression of medium-sized payload

The chart in Figure 7 shows a typical DataSet instance (which this article's sample application uses) that is stored as XML. The original file size (the complete circle) is about 190 KB, and the compressed size (the green part of the chart) is reduced to about 12 KB—a storage save (the orange part of the chart) of more than 93 percent! The difference is not that interesting for small payloads, but as payloads get larger, the gain increases.

For more general details about data compression, see the article Developing Screen Orientation-Aware Applications.

Northwind Pocket Analyze Application Walkthrough

The sample client scenario is a Smartphone application that is written with Microsoft Visual Studio .NET 2003 in C# and targets the Microsoft .NET Compact Framework. The sample uses the Smart Device Framework from OpenNETCF, which is also available as source code.

The application shows how to support the decision support business process by using a Smartphone. The design choices align to the process as much as possible and also maximize efficiency for the decision maker. Some of the design choices are commented in the walkthrough. Also note that this article explores parts of the code after it describes the application user interface design.

Main Screen

When the user starts the application, the first screen is the main screen, as shown in Figure 8.

Figure 8. Main screen

The main purpose of this screen is to retrieve data to be analyzed. When the user opens the application, the application searches for available data feeds in the local store. When the user selects a feed in the list (by pressing the hardware's number button that corresponds to the number of the feed or by pressing the hardware's Action key, which is normally in the middle of the hardware's direction keys), this action has the same result as selecting the View command. Selecting View shows the details about the feed. Selecting Analyze initiates a retrieval and analysis of the feed data, which this articles discusses in more detail in the next section.

The Offline command indicates that the user wants to work in a forced offline mode (when there is a network connection). One reason to work offline is to save network traffic (and thereby cost when using an expensive connection) because the feeds that the application saved locally may have sufficiently current information.

Figure 9 shows the main screen on a Smartphone with a QVGA display.

Figure 9. Main screen on a QVGA display

Note how the list is resized to fit the available space. The list allows ten items to be shown (as in other applications on Smartphones with QVGA display), but Figure 9 does not show this capability. A QVGA screen is relatively larger in height (320 pixels compared to a normal resolution of 220 pixels—about 45 percent larger) than in width (240 pixels compare to a normal resolution of 176 pixels—about 36 percent larger). The only other visual effect is that the fonts are clearer due to the higher resolution.

If the user selects the Offline command (to remove the check mark) and puts the application in online mode (if a network connection is available), the Login screen appears, as shown in Figure 10.

Figure 10. Login screen

The Username box is populated (if the user enters this information in the Options screen as described in the Options section of this article), and the application uses this information when it connects to the XML Web service.

If the device is online (connected to a network and thereby to a server), and the user selects the Get Feeds command, a XML Web service calls the server to retrieve the list of available feeds. The application also saves this feed list locally to be used during later requests when the device is offline.

When the user selects the View command on the main menu screen, the Feed details screen appears, as shown in Figure 11.

Figure 11. Feed details screen

On this screen, the user can review information about the feed, find out when the feed was last downloaded from the server, view the size of the feed, the local space that is required to store the feed (this information is in parentheses), and read a description about the feed's information. The difference between the two sizes is the result of the data compression used for storing local data.

Figure 12 shows the Feed details screen on a Smartphone with a QVGA display.

Figure 12. Feed details screen on a QVGA display

Due to the larger size, the controls resize and reposition to better fit the higher resolution. The font size, however, is not changed because the operating system automatically adjusts its size.

When the user selects the Description box (by pressing the Action key), the description appears in a full-screen view, as shown in Figure 13.

Figure 13. Feed description

Even though the description appears to be in edit mode, it cannot be updated. Any changes the user makes to it are discarded whether the user selects Done or Cancel.

Analyze

When the user selects Analyze on the main menu screen, the application initiates a retrieval of the selected feed. If the device is online—and is not forced offline—an XML Web service call is made to the server to retrieve the feed. The application also saves this feed locally to be used for later requests when the device is offline. When the application retrieves the feed, the View screen displays and allows the user to define the view, as shown in Figure 14.

Figure 14. View screen

The user defines the view by selecting what columns (dimensions), which are available, should be analyzed. The selections in Figure 14 will display the quarters as columns and the employees as one row each. The data will come from the amount column (in this example, total sales), and the data will be calculated as sums for each cross-section (there is also an average formula option available).

Figure 15 shows how the View screen looks on a Smartphone with a QVGA display.

Figure 15. View screen on a QVGA display

Again, the controls resize and reposition to better fit the higher resolution.

When the user selects the Column (or Row) box, the application presents the available options in full-screen view, as shown in Figure 16.

Figure 16. Available options to choose from

When the user presses Done on the View screen, the Analyze screen with the pivot table is displayed, as shown in Figure 17.

Figure 17. Analyze screen displaying a pivot table

Figure 17 shows a pivot table with the data organized according to the user's selections on the View screen in Figure 14. The sales figures are summed for each employee for each time period (in this example, quarters). For each quarter, the pivot table also calculates a total. Each row also has a total, and the last cell at the bottom of the pivot table is the grand total. The Menu menu is shown in Figure 18.

Figure 18. Analyze screen menu

To return to the definition of the view on the View screen (Figure 14), the user selects the View command. This article describes the Chart command in the next section.

Figure 19 shows the Analyze screen on a Smartphone with a QVGA.

Figure 19. Analyze screen on a QVGA display

Figure 19 shows that the application can display more data due to the higher resolution.

Navigation of the grid is done with the direction keys, and the movement is one cell at a time. If the grid is scrolled to the last cell, the screen will look like Figure 20.

Figure 20. Analyze screen scrolled to the right

When the user selects the Save command, the application saves the current content of the pivot table to a file in tab-separated format because this format allows the user to open the data in applications like Microsoft Word or Microsoft Excel. When the user saves the file, the application displays a confirmation message, as shown in Figure 21.

Figure 21. Confirmation that the pivot table data is saved to file

The application saves the file in the \Storage\My Documents folder and automatically generates a unique name (such as table0.txt or table1.txt). The user can then transfer the table data file (by means of ActiveSync) or attach the file to an e-mail message to be further manipulated on a desktop computer or server. To send the file as an attachment, the user can use a tool like AttachSmart.

Chart

The Chart screen is displayed, as shown in Figure 22, when the user selects the Chart command from the Analyze screen's menu.

Figure 22. Chart screen

When the application opens the Chart screen, the default chart type is a line chart. The scale of the y-axis is adjusted to fit the data, and in Figure 22, the data is divided by 100 making the top of the y-axis equal to $70 000. Figure 23 shows the Chart screen on a Smartphone with a QVGA display.

Figure 23. Chart screen on a QVGA display

Note how the higher resolution clearly shows the chart and the labels.

In Figure 24, the user selected the Legend command. This figure also shows the Chart screen's other commands.

Figure 24. A chart with a legend (and the available commands)

The user shows the legend by selecting the Legend command. If the user selects this command again, the legend is removed. The legend shows a guide to each of the series in the chart. In this example, the series corresponds to the rows in the pivot table (which correspond to employees) as shown in Figures 17. Each point on the x-axis corresponds to a category, which are the columns of the pivot table (which correspond to quarters).

Figure 25 shows the same screen as Figure 24—except on a Smartphone with a QVGA display.

Figure 25. A chart with a legend (and the available commands) on a QVGA display

Because the legend might cover important information in the chart, the user can move the legend by using the direction keys. Pressing the Action key toggles the legend to move in large and small movements. If the user does not press the Action key, the direction keys move the legend in large steps (10 pixels); if the user presses it once, the direction keys move the legend in small steps (1 pixel).

The Trend command is a very interesting because it calculates a linear trend for each of the chart's series, as shown in Figure 26. Note also how the application repositioned the legend.

Figure 26. Trend chart

The application calculates the trend by using linear regression and the least square method. A trend chart is a very effective way to view the information because it often says much more than the raw data. Compare the trend chart in Figure 26 with the exact same raw data in Figure 22—you can see the difference.

Figure 27 shows the same screen as Figure 26—except on a Smartphone with a QVGA display.

Figure 27. Trend chart on a QVGA display

When the user selects Save, the application saves the chart that is currently displayed (including the legend) as a file. A confirmation message appears, as shown in Figure 28.

Figure 28. Confirmation message to save a chart as a file

The application saves the file in the \Storage\My Documents folder, and the application automatically generates a unique name (for example, chart0.bmp or chart1.bmp). The user can transfer the chart image file (by means of ActiveSync) or attach it to an e-mail message to be further manipulated on a desktop computer or server.

The user can also flip data by selecting the Flip command. The series and categories (x-axis and y-axis) switch locations on the chart. The legend updates accordingly, as shown in Figure 29.

Figure 29. A flipped chart and an updated legend

Because the application can flip charts numerous times, this could be a quick way for the user to see the x-axis values (because the values are not shown to save screen space). A flip generates a new chart (which is not the case for Legend, Trend, and Save), and each time the application generates a new chart, the application generates a new set of colors for the series. The colors are generated randomly, so it can be practical for a user to flip the chart a number of times until a satisfying color combination is achieved.

Figure 30 shows the same screen as Figure 29—except on a Smartphone with a QVGA display.

Figure 30. A flipped chart and an updated legend on a QVGA display

The Bar command toggles the chart type between a line chart (which this article discussed previously) and a bar chart, as shown in Figure 31.

Figure 31. Bar chart

Figure 31 shows a stacked bar chart where all of the series values are added, and those values show the total sales per employee. Though not shown in the chart, the fifth x-axis value is the total sales for Margaret Peacock (refer to the legend in Figure 27 for the order of employees). Again, the application the y-axis to fit the data this new chart displays; in Figure 31, the data is divided by 1000, making the top of the y-axis equal to $300,000. The application also generates a new set of colors. Note how the colors that are generated for bar charts are lighter than the colors for line charts—these colors improve the appearance of the chart. When the application shows a bar chart, the application changes the Bar command to Line to allow the user to switch to a line chart.

Figure 32 shows the bar chart on a Smartphone with a QVGA display.

Figure 32. Bar chart on a QVGA display

Again, note how the higher resolution adds more detail to the chart.

Report

As previously mentioned, the user can save the analysis data from the pivot table in a tab-separated text file and transfer the file to a desktop computer. A user can also save a chart as an image file that can be transferred to a desktop computer. With those two files, the user can easily put together a nice looking sales report in Microsoft Word, as shown in Figure 33.

Click here for larger image

Figure 33. Sales report using the chart and pivot table data. Click the thumbnail for a larger image.

The user can simply insert the chart image in the document and import the table from Microsoft Excel—the program that opens the table text file.

Options

The Options screen, as shown in Figure 34, is displayed when the user selects the Options command on the main menu screen.

Figure 34. Options screen

The Web Service (URL) box shows the URL for the XML Web service that is used to retrieve both the list of available feeds and the individual feeds. The Server Login (Username) box shows the default user name when the device connects to an XML Web service.

Figure 35 shows the Options screen on a Smartphone with a QVGA display.

Figure 35. Options screen on a QVGA display

The resized input fields allow the device to display slightly more information.

About

All applications should include a screen with the product name, version, copyright, and other legal information. On the main screen, the About command displays this information, as shown in Figure 36.

Figure 36. About the application

This screen can also include a link to a Web page with product and support information. Figure 37 shows the same screen as Figure 36—except on a Smartphone with a QVGA display.

Figure 37. About screen on a QVGA display

Because the application supports globalization (and localization), the next section shows some translated screens.

World Ready

When the user changes Locale in the regional settings (by selecting Start, Settings, More, and then Regional Settings) to Portuguese (Brazil) and then restarts the application, the complete sample application is translated. The following figures are the Brazilian Portuguese versions of the screens that are shown in Figures 8, 11, 14, 18, 24, 34, and 36.

Figure 38 shows the translated main screen. The form's title and the menu commands are translated.

Figure 38. Translated main screen

Figure 39 shows the translated Feed details screen. The form's title and controls (labels) are translated. Also note that the date format has changed according to the current locale.

Figure 39. Translated Feed details screen

Figure 40 shows the translated View screen. The labels and the formula options are translated.

Figure 40. Translated View screen

Figure 41 shows the translated Analyze screen. The title and commands are translated.

Figure 41. Translated Analyze screen

Figure 42 shows the translated Chart screen. Again, the title and commands are translated.

Figure 42. Translated Chart screen

Figure 43 shows the translated Options screen.

Figure 43. Translated Options screen

Finally, Figure 44 shows the translated About screen.

Figure 44. Translated About screen

All of the screens are translated when shown on a Smartphone with a QVGA display as well.

This concludes the walkthrough of the client application, and now this article describes some of the source code.

Code Walkthrough

The previous section provided an example client scenario for the Pocket Analyze application, and now it's time to look at the source code for that sample. The general parts of the code are covered in the article Northwind Pocket Service: Field Service for Windows Mobile 2003-Based Smartphones, so this article focuses on some of the topics that are unique for this sample.

Analysis Data

A good place to start is to look at how the analysis data is stored, created, and distributed. The actual data to be analyzed is included in the sample database, which is an enhanced version of the Northwind sample database. It includes basic information about employees, sales orders, service engagement, requested deliveries, and so on.

To structure the analysis data, a new Feeds table was created with the following code example to hold the feeds (queries).

CREATE TABLE Feeds (
    FeedID NVARCHAR(20) PRIMARY KEY NOT NULL,
    FeedName NVARCHAR(50) NOT NULL,
    [Description] NVARCHAR(256) NULL,
    Query NVARCHAR(4000) NOT NULL
)

It includes an identifier name in the FeedID column, a name of the feed in the FeedName column, and a long description in the Description column. The most interesting column is the Query column that holds the actual specification of the feed. This column holds the SQL SELECT statement to be submitted to extract the feed from the database. A typical feed specification looks like the following code example.

SELECT (E.FirstName + ' ' + E.LastName) Employee,
    C.CompanyName Customer, S.CompanyName Shipper,
    CONVERT(NVARCHAR(10), O.OrderDate, 120) [Date],
    RIGHT(CONVERT(NVARCHAR(4), DATEPART(year, O.OrderDate)), 2) [Year],
    RIGHT(CONVERT(NVARCHAR(4), DATEPART(year, O.OrderDate)), 2) + '-Q' +
    CONVERT(NVARCHAR(2), DATEPART(quarter, O.OrderDate)) [Quarter],
    RIGHT(CONVERT(NVARCHAR(10),DATEPART(year, O.OrderDate)), 2) + '-' +
    RIGHT('0' + CONVERT(NVARCHAR(2), DATEPART(month, O.OrderDate)), 2)
    + ' ' + CONVERT(NVARCHAR(3), DATENAME(month, O.OrderDate)) [Month],
    ROUND(SUM(D.UnitPrice * D.Quantity * (1 - D.Discount)) +
    O.Freight, 0) Amount
FROM Orders O JOIN OrderDetails D ON O.OrderID=D.OrderID
    JOIN Customers C ON O.CustomerID=C.CustomerID
    JOIN Employees E ON O.EmployeeID=E.EmployeeID
    JOIN Shippers S ON O.ShipVia=S.ShipperID
GROUP BY E.LastName, E.FirstName, C.CompanyName, S.CompanyName,
    O.OrderDate, O.Freight

Table 1 shows a typical output from this feed.

Table 1. Feed data output

Employee Customer Shipper Date Year Quarter Month Amount
Steven Buchanan Berglunds snabbk öp Speedy Express 1997-09-02 97 97-Q3 97-09 Sep 657
Steven Buchanan Berglunds snabbköp Speedy Express 1998-02-03 98 98-Q1 98-02 Feb 1205
Steven Buchanan Blondesddsl père et fils United Package 1996-09-04 96 96-Q3 96-09 Sep 1426
Steven Buchanan Bon app' Speedy Express 1997-11-05 97 97-Q4 97-11 Nov 504
Steven Buchanan Chop-suey Chinese United Package 1996-07-11 96 96-Q3 96-07 Jul 580
Steven Buchanan Familia Arquibaldo Federal Shipping 1997-08-29 97 97-Q3 97-08 Aug 1956
Steven Buchanan Folk och fä HB Federal Shipping 1996-12-10 96 96-Q4 96-12 Dec 109

All of the columns, except the Amount column, is the categorization of the analysis data—commonly referred to as the dimensions. The dimensions are used to compare different groupings of information. The last column in Table 1 holds the value to be analyzed. This value is the total sales per date (calculated as unit price x quantity – discount for all order details + freight).

To access the analysis data in a structured way, a stored procedure (spGetFeed) is created by the following code example.

CREATE PROCEDURE spGetFeed @feedID NVARCHAR(20)
AS
DECLARE @sql NVARCHAR(4000)
SELECT @sql = Query FROM Feeds WHERE FeedID = @feedID
EXEC(@sql)
GO

When the stored procedure is supplied with the feed identifier feedID), the feed specification (Query) is retrieved from the Feeds table and is executed to produce the returned result set. Although this stored procedure could be published directly from SQL Server 2000 by using SQLXML, a straightforward XML Web service is created with the following code example.

[WebMethod]
public DataSet GetFeedList()
{
    DataSet ds = new DataSet();
    using(SqlConnection cn = new SqlConnection(this.connectionString))
    {
        cn.Open();
        SqlDataAdapter da = new SqlDataAdapter("SELECT FeedID,
            FeedName, Description FROM Feeds ORDER BY FeedName", cn);
        da.Fill(ds);
    }
    return ds;
}

[WebMethod]
public DataSet GetFeed(string feedID)
{
    DataSet ds = new DataSet();
    using(SqlConnection cn = new SqlConnection(this.connectionString))
    {
        cn.Open();
        SqlCommand cmd = cn.CreateCommand();
        cmd.CommandType = CommandType.StoredProcedure;
        cmd.CommandText = "spGetFeed";
        cmd.Parameters.Add("@feedID", feedID);
        SqlDataAdapter da = new SqlDataAdapter(cmd);
        da.Fill(ds);
    }
    return ds;
}

The first method is used to get the list of available feeds by using a direct query on the database table Feeds, and the second method is used to retrieve the feed result by calling the stored procedure spGetFeed. The private class variable connectionString that is holding the connection string is declared as shown in the following code example.

private string connectionString =
    ConfigurationSettings.AppSettings["ConnectionString"];

With a reference to the correct namespace ("System.Configuration"), this declaration extracts the following application setting from the configuration file (Web.config), as shown in the following code example.

<appSettings>
    <add key="ConnectionString" value="data source=(local);initial
        catalog=NorthwindX;integrated security=SSPI;"></add>
</appSettings>

These lines of code make it easier for you to manage the connection string.

On the client side, the following code calls the two Web methods, which are in the RemoteHandler class.

public DataSet GetFeedList()
{
    WebServices.Analyze analyzeWebService = new WebServices.Analyze();

    // Set the URL of the Web service
    analyzeWebService.Url = Common.Values.WebServiceUrl;

    // Set the credentials
    analyzeWebService.Credentials =
        new NetworkCredential(Common.Values.UserName,
        Common.Values.Password);

    // Get the list of feeds
    DataSet ds = analyzeWebService.GetFeedList();

    return ds;
}

public DataSet GetFeed(string feedID)
{
    WebServices.Analyze analyzeWebService = new WebServices.Analyze();

    // Set the URL of the Web service
    analyzeWebService.Url = Common.Values.WebServiceUrl;

    // Set the credentials
    analyzeWebService.Credentials =
        new NetworkCredential(Common.Values.UserName,
        Common.Values.Password);

    // Get the feed
    DataSet ds = analyzeWebService.GetFeed(feedID);

    return ds;
}

The settings on the Options screen (see Figure 34) set the URL of the XML Web service. The user enters credentials once on the Login screen (see Figure 10).

A DataSet instance is used for the data transport. But when a DataSet instance is used with an XML Web service, it is actually the XML representation of the DataSet. Because XML is text based and also includes extensive metadata (such as schema and tag names), it adds up quickly to produce large chunks of information that need to be transferred and later stored.

To optimize communications, a very interesting option is available in most Web servers (like Internet Information Services 6.0)—use HTTP (1.1) compression. With this technology, both requests and responses to the server can be compressed by using the gzip or deflate (also known as zip) formats. To store XML data more efficiently, you can also use the same compression (deflate) technology for saving (DataSet) XML in archive files (.zip files). Because the savings are drastic and the loss of performance is negotiable, this is a valid option. For more details, see the Data Compression section in this article.

Resolution Awareness

To make an application aware of the screen's resolution, the application needs to retrieve the size of the screen to make the desired adjustments to the user interface. In a .NET Compact Framework application, the current size of the screen can be retrieved from the Screen class in the "System.Windows.Forms" namespace. You can use its singleton instance, PrimaryScreen, to get information about the screen, and the WorkingArea property (of type Rectangle) specifies the screen area excluding the title and soft keys (menus).

To store the information about the resolution, two properties are defined in the Common class. The first property holds the size of the screen, as shown in the following code example.

private static Size screen;
public static Size Screen
{
    get { return screen; }
}

The second property is a flag that indicates if this is a normal (or classic) Smartphone screen size, as shown in the following code example.

private static bool normalScreen;
public static bool NormalScreen
{
  get { return normalScreen; }
}

Those two properties are set when the application opens, as shown in the following code example.

private void setScreen()
{
    screen = new Size(System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Width,
        System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Height);
    normalScreen = (screen.Width == 176);
}

With this code in place, you can write the code to rearrange the forms—beginning with the About form. You need to add the following code to the Load event.

private void AboutForm_Load(object sender, System.EventArgs e)
{
    resize();
}

The private method should contain the following code.

private void resize()
{
    if(!Common.NormalScreen)
    {
        ArrayList controls = new ArrayList();
        foreach(Control c in this.Controls)
            controls.Add(c);
        Common.ResizeControls(controls);
    }
}

The user interface is designed for a normal Smartphone display (176 pixels x 220 pixels); and if the code is run on such a device, the application does not need to make any changes to the layout. But, if the application is running on a Smartphone with a different screen resolution, the previous code fills the array list controls with the controls from the Controls collection of the form. Note that the controls are assumed to appear in the Controls collection in the correct (tab) order. The tab order is necessary anyway for correct navigation among the controls in the form. Then, a call is made to a helper method, as shown in the following code example.

public static void ResizeControls(ArrayList controls)
{
    foreach(Control c in controls)
    {
        c.Top = (c.Top - 2) / 22 * 26 + 4;
        c.Width = Common.Screen.Width - c.Left * 2;
        c.Height = c.Height / 22 * 26;
    }
}

To understand the calculations the application makes, it's necessary to say a few words about the form design. All of the forms in the sample application is designed according to design guidelines for Smartphone; each control occupies 22 pixels vertically and the full width minus a margin of 4 pixels on each side. Because the form designer in Visual Studio does not allow the user to set some controls (like TextBox and ComboBox) to the desired height, this adjustment needs to be implemented as code (as shown in the following code example). The first control has a top margin of 2 pixels. With this design in place, you can calculate each control's vertical position by dividing the Top property by 22 after you remove the top margin. A recommended control height for the QVGA display is 26 pixels, and a suggested top margin is 4 pixels. Therefore, you can multiply the vertical position of the control (the Top property without the margin divided by 22) by 26 and add 4 for the margin. Because some controls can occupy more than one logical item vertically on the form (which is the case for the copyright and comment labels on the About form), you can calculate the height in a similar way as the vertical position.

With the same code inserted in the Load event, the following code shows the private method in the Analyze form, AnalyzeForm.

private void resize()
{
    if(Common.NormalScreen)
    {
        this.columnComboBox.Height = 22;
        this.rowComboBox.Height = 22;
        this.dataComboBox.Height = 22;
        this.formulaComboBox.Height = 22;
    }
    else
    {
        ArrayList controls = new ArrayList();
        foreach(Control c in this.Controls)
        {
            switch(c.GetType().Name)
            {
                case "Label":
                case "ComboBox":
                    controls.Add(c);
                    break;
            }
        }
        Common.ResizeControls(controls);
        gridPanel.Size = Common.Screen;
        dataGrid.Width = Common.Screen.Width + 3;
        dataGrid.Height = Common.Screen.Height + 2;
    }
}

In this example, this is a normal Smartphone display; only designer flaw adjustments (for example, the TextBox controls cannot be set to a height of 22 pixels in the form designer) are made. The automatic resize of the controls (which are used for the View form) should only include the Labels and ComboBox controls; therefore, you need to add only these types to the controls array before it is passed to the helper method, ResizeControls. Finally, the grid control (and its wrapping panel) is resized to fit the complete screen.

For more details about resizing other forms, see the Northwind_Traders_Decision_Support_SP.msi.

There is better support for making forms screen-orientation aware in the .NET Compact Framework version 2.0.

Hardware Key Navigation

The Chart form (ChartForm) implements keyboard navigation where the user can move the legend. The following code example handles the navigation (in the form's KeyDown event).

private bool legendMoveSmallStep = false; 
private void ChartForm_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
{
    if(!legendPictureBox.Visible)
        return;

    int step = 10;
    if(legendMoveSmallStep)
        step = 1;

    switch(e.KeyCode)
    {
        case Keys.Left:
            if(legendPictureBox.Left > 4)
                legendPictureBox.Left -= (int)Math.Min(step,
                    legendPictureBox.Left - 4);
            break;

        case Keys.Right:
            if(legendPictureBox.Left < Common.Screen.Width –
                    legendPictureBox.Width - 4)
                legendPictureBox.Left += (int)Math.Min(step,
                    Common.Screen.Width - legendPictureBox.Width - 4 –
                    legendPictureBox.Left);
            break;

        case Keys.Up:
            if(legendPictureBox.Top > 28)
                legendPictureBox.Top -= (int)Math.Min(step,
                    legendPictureBox.Top - 28);
            break;

        case Keys.Down:
            if(legendPictureBox.Top < Common.Screen.Height –
                legendPictureBox.Height - 4)
                legendPictureBox.Top += (int)Math.Min(step,
                    Common.Screen.Height - legendPictureBox.Height - 4 –
                    legendPictureBox.Top);
            break;

        case Keys.Enter:
            legendMoveSmallStep = !legendMoveSmallStep;
            break;
    }
}

The private class variable, legendMoveSmallStep, is used to indicate whether the movement should be small or large (the default size). Small movements are one pixel at a time, and large movements are ten pixels at a time. The user toggles between these movements by pressing the Action key. Depending which direction key (left, right, up, or down) the user presses, the user moves the legend accordingly. Note that the boundaries of where the user can move the legend are within an area that is the size of the chart's picture box.

Data Compression

The most common formats for data compression are gzip (RFC 1952) and deflate (RFC 1951).

Deflate is also most often referred to as the zip format because it is the format that is used for common .zip files and that is used to compress local data in the sample application. This format was chosen because the data exchange with the computer (server/desktop computer) environment is greatly simplified. For example, a set of fresh feeds could be sent to the Smartphone by means of sending an e-mail message (providing that it is equipped with a tool like AttachSmart that allows attachments to be saved) or put on a Web server for the user to directly download it from Pocket Internet Explorer on the Smartphone. The e-mail message with the attached feeds could be a backup option to the XML Web service that provides the updated feeds in real-time and that is also compressed. The offline data store (.zip file) could also be shared between users by means of infrared transfer.

In the sample application, the compression of XML Web service calls use the HTTP 1.1 standard (RFC 2616). Because the gzip format is the preferred format according to the HTTP 1.1 standard, the gzip format is the preferred format for the sample to use as well.

For more details, see the article >Northwind Pocket Analyze: Decision Support for Windows Mobile-based Pocket PCs.

Connection Awareness

A command in the main form gives the user the ability to control the connection state. The command is selected by default, putting the application in an offline mode. The application will not make any attempts to connect to the XML Web service to retrieve information about the feeds (or the feeds themselves). The application will retrieve all feed data from the local data store. The implementation of the offline command looks like the following code.

private void offlineMenuItem_Click(object sender, System.EventArgs e)
{
    offlineMenuItem.Checked = !offlineMenuItem.Checked;
    Common.Values.Offline = offlineMenuItem.Checked;

    // If online, and the password is not set, get the password
    if(!Common.Values.Offline && Common.Values.Password == null)
        FormCache.Instance.Push(typeof(LoginForm));
}

The state toggles according to the commands the user selects, and the application saves the current state in the singleton instance Values of the Common application class.

Each time the application needs to check whether a device is connected, it uses a helper class named CheckConnectionHelper, as shown in the following code example.

if(CheckConnectionHelper.CheckConnectedState())
{
    // Do something if a device is connected
}
else
{
    // Do something else if a device is not connected
}

The implementation looks like the following code example.

public static bool CheckConnectedState()
{
    if(Common.Values.Offline)
        return false;
    int connectionDescription = 0;
    return InternetGetConnectedState(out connectionDescription, 0);
}

This method always return false if the user has forced the device to use the offline mode (by using the previously mentioned command).

The required API declaration looks like the following.

  [DllImport("wininet.dll")]
private extern static bool InternetGetConnectedState(
    out int connectionDescription, int reservedValue);

This declaration only checks whether the device has a valid network connection, but it does not guarantee that the device is able to reach any other peer or host by means of the network. For a more accurate check that makes a HTTP connection attempt against a specific host, see the other code in the CheckConnectionHelper class.

The connection awareness (whether to retrieve feed data from the remote XML Web service or the local store) is encapsulated in a separate class (DataHandler) to simplify for the developer who designs the user interface. For more information, see the article >Northwind Pocket Analyze: Decision Support for Windows Mobile-based Pocket PCs.

Pivot Table

Implementing a pivot table in the Analyze form (AnalyzeForm) makes use of a standard grid (DataGrid) control and an underlying data source (DataTable).

For more information, see the article >Northwind Pocket Analyze: Decision Support for Windows Mobile-based Pocket PCs.

Line and Bar Chart

There are several commercial products available that provide very advanced charting capabilities. You should browse the market when you consider charting in an enterprise application. Some commercial products allow you to control the source code. While you might be waiting for someone to port the excellent open source charting library ZedGraph to the .NET Compact Framework, you can find some basic charting functionality in this sample code. All of the charting is done by using managed code and the GDI+ functionality that the .NET Compact Framework offers.

The code in the sample uses a helper class to produce the chart bitmap, which is copied to a PictureBox control on the form. You can easily convert the chart helper class into a custom control; the Northwind_Traders_Decision_Support_SP.msi includes such a control (in a file named ChartAsControl.zip). But that implementation is the beginning; you must put some more work into the control to make it user friendly because there are some issues with redrawing the chart directly in the Paint event. You need to implement buffering to avoid the complete redraw of the chart each time the user moves the legend by using the direction keys. Also, to make it truly reusable, you should also add form designer support.

For more information about the implementing a chart, see the article >Northwind Pocket Analyze: Decision Support for Windows Mobile-based Pocket PCs.

Screen Capture

With thanks to fellow MVP Alex Feinman, some of his code is included in the sample application to capture the image of a control (in this case, the picture box that holds the chart) and save it to a file. The code grabs a handle to the display's native device context, creates a memory bitmap of the same size, copies the screen bits to that new bitmap, and finally saves the new bitmap to a file in standard format.

Because the files are stored in raw bitmap format, they end up quite large on discs, and you might consider investing in some component or library to compress the captured images to a more effective format (such as .jpeg or .gif). One example is the JpegTest sample by Sergey Bogdanov.

In the .NET Compact Framework 2.0, there is support for saving a bitmap (Image.Save) in many formats (such as .gif, .jpeg, .tiff, and .png).

For more information, see the article >Northwind Pocket Analyze: Decision Support for Windows Mobile-based Pocket PCs.

GlobalHandler

Any mobile enterprise application that is intended to display more than one language needs to be easily translated. Therefore, you can use the GlobalHandler class to translate complete forms, including all controls and menus. It only requires a single line of code in each form, which the following code example shows.

GlobalHandler.Translate.Form(this);

Even simple texts, such as error messages, can be translated by using the following code.

MessageBox.Show(GlobalHandler.Translate.Text("MsgCantOpenWebPage",
    "Could not open web page!"), this.Text);

For more details about the management and code related to globalization, see the article Northwind Pocket Sales: Field Sales for Windows Mobile-based Pocket PCs.

Form Cache (and Stack)

Each enterprise application that contains a large amount of forms requires that the forms, and the memory they consume, to be managed in an efficient way. Therefore, the FormCache class supports both the caching and stacking of forms. Briefly, the loading of a new form, or actually pushing a new form on the form stack, looks like the following code.

FormCache.Instance.Push(typeof(OptionsForm));

The push implicitly loads the form (if it is not already loaded). If any parameters need to be passed to the new form, the code looks like the following.

OptionsForm optionsForm = (OptionsForm)
        FormCache.Instance.Load(typeof(OptionsForm));
optionsForm.DatabaseExist = databaseExist;
FormCache.Instance.Push(typeof(OptionsForm));

For more details about the management and code related to caching and stacking forms, see the article Northwind Pocket Sales: Field Sales for Windows Mobile-based Smartphones.

Conclusion

A healthy corporate infrastructure (the digital nervous system) enables data analysis, and data analysis enables better decision making. By implementing basic pivot tables that use a grid control and that use GDI+ to do basic charting, you enable basic analysis on a mobile device. The streamlining of remote communication, like XML Web services calls and the optimization of local storage using standard compression technology, enables the extension of data analysis wherever a Smartphone can go (which is anywhere). Put that data to work in your own mobile enterprise data analysis application today!

Page view tracker