Creating the Pocket TaskVision Application: Pocket PC Development Considerations
Vertigo Software, Inc.
.NET Compact Framework
Summary: This document provides an overview of the development tasks that were unique to the Pocket TaskVision sample application. Pocket PC devices have much lower storage capacities, memory and lower-end processors than desktop systems, so storage and performance considerations are mentioned throughout the document. (7 pages)
Download the Pocket TaskVision Source Code
TaskVision is a sample smart client task management application built using the Windows Forms classes of the .NET Framework—an integral Windows component that supports building and running the next generation of applications and Web services. TaskVision allows authenticated users to view, modify, and add projects and tasks that are shared with other users. It may be used in any number of scenarios—from bug tracking to managing work orders or customer service requests. Its primary purpose is to provide quality, sample source code to developers interested in building smart client applications and Web services using the .NET Framework.
The Pocket TaskVision application is an extension of the TaskVision solution and allows users to manage tasks using Pocket PC devices in a connected or a disconnected environment. It uses the same Web services as the TaskVision application: Authentication service to authenticate users and Data service to manage tasks. SQL CE is used for local storage when working offline. An overview is shown in Figure 1.
Figure 1 Overview of the Pocket TaskVision application
You may access TaskVision and Pocket TaskVision at the TaskVision home page. Once you have installed either application, use the following credentials to log in and access the applications’ functionality:
User name: jdoe
Pocket TaskVision supports a subset of TaskVision features. It allows users to manage tasks in online or offline mode but does not allow users to manage projects (create new projects for example) or manage users (delete a specific user from the database). The following features are supported:
- Runs on Pocket PC devices using the .NET Compact Framework.
- Manages tasks: view, modify, delete and create new tasks.
- Enables you to work online or offline. Select projects to take offline and then synchronize changes when an Internet connection is available.
- Uses SQL CE for local storage when working offline.
- Resolves conflicts: allow the user to specify what information is persisted to the database when the same task is modified by multiple users.
- Uses local config file to store settings and default values.
- Provides a custom task list control that is Pocket PC-friendly.
- Filters task lists.
- Provides a custom DateTimePicker control to enter task dates.
- Keeps the task list updated with the master database by executing an asynchronous Web service method.
Classes are divided into four main categories, as shown in Figure 2.
- Window Forms collect and display information to the user.
- Custom Controls are individual control elements on a form that derive from the System.Windows.Forms.Control class.
- Data Access contains classes that are responsible for storing and managing data; the source of the data can be the Web service or the local SQL CE database.
- Finally, the Util classes provide various functions, such as managing settings in the config file, encrypting passwords, and interacting with Web services.
Figure 2 Class categories of the Pocket TaskVision application
An obvious difference in Pocket TaskVision versus TaskVision is running on a smaller display surface. Pocket TaskVision screens were designed to fit on smaller screens with a different aspect ratio (taller than wide).
Tabs allow more information to be displayed in a single window by grouping related content under different tabs. For example, Pocket TaskVision displays data collision information in a tabbed window with Local and Server tabs (Figure 3).
Figure 3 Displaying data collisions
The .NET Compact Framework supports the DataGrid and ListView controls, but they are not always the best option because they force the user to scroll horizontally. Pocket TaskVision uses a custom list control called TaskListControl that displays several lines of information in each row and only scrolls vertically (Figure 4).
Figure 4 Displaying tasks using the custom TaskListControl
The TaskListControl is an example of a custom control. A custom control is a class that derives from System.Windows.Forms.Control that implements all aspects of a control. For example, the custom list control stores the task list, draws each task item, highlights rows, performs hit testing, and so on. Creating custom controls is more common on the Pocket PC since the .NET Compact Framework does not allow you to customize drawing of standard controls (it’s all or nothing).
The .NET Compact Framework also does not support the Control.SetStyle method that allows you to enable double buffering and ignore erase background messages. Both of these are important when creating flicker-free controls. Pocket TaskVision follows this general design pattern for custom controls:
- Detect first time painting. Create a memory bitmap of the same size as the control and GDI objects that are required for drawing (brushes, pens and fonts). This provides better performance than creating GDI objects in every paint event.
- Override OnPaint and draw on the memory bitmap, then draw the bitmap to the screen. This is known as double-buffering and prevents flashing.
- Override OnPaintBackground to prevent Windows from erasing the background and causing flicker.
The same actions will take longer on the Pocket PC than a desktop system, so it is important to provide proper feedback. Pocket TaskVision displays the wait cursor when busy, displays a custom progress control for additional feedback, as well as logging events when appropriate. Look at Figure 5.
Figure 5 Displaying feedback while information is updated
All windows are full-screen in the.NET Compact Framework, but sometimes you want to use a popup dialog. Pocket TaskVision displays a popup window when the user specifies a custom filter in the task list (Figure 6). This is not a popup dialog like you would use in a desktop application; rather, it is a panel control that is hidden and shown to simulate a popup dialog.
Figure 6 Displaying a popup window by using a panel control
For better performance, you can also hide and show entire forms instead of creating and initializing the form each time. Pocket TaskVision creates the task list window once and then changes the visible state instead of actually closing the window.
Additionally, creating instances of objects the first time they are required instead of assuming they should be created in form load improves performance. Each object instantiation takes time, and the combination of all objects can add up to a noticeable difference in the time it takes the form to load. If a form does take a long time to load, you can force it to display right away so it doesn’t seem to take as long to the user.
Not all controls are available in the .NET Compact Framework. An example is the DateTimePicker control. The underlying operating system supports the control, but the .NET Compact Framework does not provide a class for you. This is an important UI element for Pocket TaskVision, so a purely managed version of the DataTimePicker control was created (Figure 7).
Figure 7 Displaying the DateTimePicker control
Minimize Keyboard Input
Pocket TaskVision eliminates as much keyboard input as possible. It uses dropdown lists when appropriate, and remembers values by storing them in the config file. Some values that are stored and restored are: login name and password, settings such as service location and timeout, last selected project and task filter selection. When creating a new task, Pocket TaskVision defaults values to the values used for the previous new task. For example, it selects Bob Smith for you if that’s to whom you assigned the last task.
The .NET Compact Framework lacks configuration file support, so Pocket TaskVision uses a custom settings class that reads and writes settings to a standard config file. Sensitive data, such as login password, is encoded before storing in the config file.
Context menus are very easy to hook up to forms or controls and can be used to reduce typing. For example, Pocket TaskVision contains a Last Location context menu that allows the user quickly to specify the last Web service location instead of retyping it.
Both TaskVision and Pocket TaskVision work in connected and disconnected environments. Both access data from the Web service when running in online mode but the two differ when working offline: TaskVision uses local files and Pocket TaskVision uses the SQL CE database for local storage.
The DataSet methods ReadXml and WriteXml can be used on the Pocket PC, but you will notice performance issues when working with larger sets of data; so Pocket TaskVision uses a SQL CE database. There is not a set rule that defines when SQL CE should be used; it depends on the amount of data, data relationships, query types, update frequency, etc.
Accessing Online and Offline Data
The location of the data is transparent to the UI code. For example, the UI requests a list of projects, but it does not know if the list came from a remote database through the Web service or a SQL CE database on a local device. The UI code does not have 'if online do this, otherwise do this' throughout the code.
The Pocket TaskVision code contains an IDataAccess interface that defines the data access interface and two classes that implement the interface: DataOnline and DataOffline. DataOnline accesses data using the Web service, while DataOffline uses the local SQL CE database, as shown in Figure 8 below.
Figure 8 The location of data is transparent to the UI code
Working with SQL CE
The local SQL CE database is used for temporary storage when users work offline. The database is treated like a data file that is created and destroyed as needed, instead of a permanent database; for example, the database is dynamically created (tables and indexes) when the user takes projects offline, and deleted after the projects are synchronized with the master database. This reduces the amount of storage necessary for the application.
Data connections are left open for better performance. Instead of opening a connection, executing a SQL command, and then closing the connection for each query, the connection is opened once and then closed when the application terminates. SQL CE only allows one connection to the database, so opening an already open connection will throw an exception.
Queries return DataSet objects instead of higher-performing DataReader objects. This is due to the data storage encapsulation design. The Web service returns the data in DataSets so that the data returned from the local storage is returned in the same object type.
Pocket TaskVision uses the same Web services as TaskVision. The Authentication service authenticates users and the Data service works with projects and tasks. Most Web service calls are performed synchronously, but the task list is kept up to date by making an asynchronous service call. The asynchronous call runs on a separate thread; however, the UI is slightly less responsive while the call is active.
The .NET Compact Framework has limited serialization support, so this means that it has trouble working with typed-DataSets. Visual Studio .NET generates proxy classes when a web reference is made to the Web service. The TaskVision Data service contains typed-DataSets and Visual Studio generates a proxy class with a lot of serialization code. This code needs to be commented out before the project will compile. Developers need to be aware of this so they aren't shocked that their project doesn't compile after adding a Web reference that contains typed-DataSets.
Performance is a little slow when consuming Web services that use DataSets. The bottleneck is the .NET Compact Framework populating the DataSet object. Performance is not an issue with Pocket TaskVision since it works with one task at a time when online and performs batch updates when working offline. You can pass data back and forth in arrays instead of DataSets for higher performance.
Users can specify the location of the Web services as well as the timeout value from the settings window (Figure 9). The settings are stored in the local config file, so they can be restored the next time the application is launched.
Figure 9 The Settings window
TaskVision and Pocket TaskVision reuse code at the Web service level; different clients consume the same Web services. You can reuse code at the source code level by wrapping any desktop or Pocket PC specific code in conditional compile directives. For example, DataSet.GetChanges is not supported in the .NET Compact Framework, so you need to manually implement this feature for the Pocket PC project.
Debugging is similar to desktop applications and you have the option of using an emulator or a real Pocket PC device. The debugger runs a little slower, so it takes longer to examine all of the properties of a DataSet object when debugging a Pocket PC application instead of a desktop application.
The Web services are not running on the Pocket PC, so make sure you don't specify
localhost for the service URL path. You should use the server name or IP address.
The Pocket PC supports smart-minimize, which hides applications instead of closing them. The MinimizeBox property of a form defines if smart-minimize is used: choose
true to use smart-minimize (default), or choose
false to terminate the application. It's useful to turn off smart-minimize when debugging because otherwise, the process does not terminate.