Developing Mobile Applications with the Compact Framework 2.0

Download the PDF here 

Overview

Cellular phones and PDA’s have changed the way we work. For many people the built in network connectivity, email synchronization and instant on capabilities make these devices an attractive alternative to bulkier laptops.  These types of features combined with enterprise application demands have led to a new generation of Windows based mobile devices called Smart Devices. These devices built on the Windows CE operating system include the Pocket PC and Smart Phone form factors.

 

Application developers build and distribute smart device applications for Windows Mobile devices using the Visual Studio 2005 Smart Device template. This template targets applications for a subset of the .NET Framework called the Compact Framework (CF). The CF is a mobile device extension that provides managed code execution for applications built using the Smart Device template. In this article we will look at developing applications for the Compact Framework and Visual Studio 2005. We will start with an overview of the CF and examine how this impacts application design and features. We will also cover the Compact Framework application development process.

Developing Smart Device Applications

Windows Mobile Smart devices are built on the Windows CE operating system and combined with a mobile version of Microsoft Office. This core set of features enables users to interact with Office documents, synchronize email and manage calendaring information with Exchange servers.

Figure 1 The Pocket PC Software Input Panel

 

Fundamentally, smart devices are found in two hardware based form factors. The Pocket PC is a data centric customized PDA containing a digitizer as the primary interface. This enables a touch screen and stylus based interaction with an on screen keyboard called the Software Input Panel (SIP) as shown in Figure 1. Many of the newer Pocket PCs are equipped with a thumb keyboard designed for typed data entry that reduces the use of a stylus. The Smart Phone as shown in Figure 2 is a phone first device with built in data capabilities. Based on the cellular handset, this type of device relies on one handed navigation using a joystick and phone pad input.

Figure  2 The Windows Mobile Smart Phone

The .NET Compact Framework Architecture

Figure 3 The Compact Framework Architecture

 

Regardless of their form factor all Windows Mobile Devices are able to install and host the Compact Framework. The CF is the smart device programming subsystem of the .NET Framework designed specifically for Windows Mobile devices. The architecture of the CF as shown in Figure 3 is similar to the .NET Framework with additional mobile enhancements. Despite their many similarities the Compact Framework was only designed to run on mobile and embedded devices.

 

Part of this is the reliance on the Windows CE operating system for core functionality and device specific features. This includes security, application setup and hardware specific features. The other is to solve the size and performance considerations that accompany application development for smaller devices. The desktop .NET framework weighs in at thirty megabytes which is a problem with the available thirty two to sixty four megabyte storage available on a typical mobile device. Application performance is also an issue. Even with the newest processors found in mobile devices they still do not have the same processor speed available to the desktop. To solve this problem meant reducing features and functionality into a two megabyte local device extension. This meant that it was necessary to remove namespaces that didn’t make sense for devices based usage and redesigning the JIT compiler to run more efficiently against targeted devices. Additionally, several types and assemblies like Windows Forms, graphics, drawing and Web Services were designed and architected specifically for mobile devices rather than copied from the full .Net Framework.

 

***Note***

The CF requires a minimum of Windows CE.NET (Windows CE Version 4.1)

 

However, the CF was designed to share the same development tools and programming model of the desktop framework. This was an intentional design to allow enterprises to leverage existing development skills for mobile application development. The goal was to keep the development paradigm as similar to Windows Forms as possible. The use of Visual Studio for both desktop and mobile development provides a common set of features. These include Intellisense, the Windows form designer with device specific controls, the object browser and an integrated debugger.  Smart device development in Visual Studio is simply a new project type.

 

Technically, the Compact Framework is a collection of locally installed dynamic link libraries. The size of the Compact Framework with all components is two megabytes. With the addition of the SQL Server 2005 Mobile Edition and it associated data providers this grows to 2.5 megabytes. By default the device stores all local data in a compressed format to further reduce the actual storage size of the framework on the device.  Table  1 shows the list of files associated with the .NET Framework 2.0.

 

Table  1: Compact Framework 2.0 Files

File

Description

Mscoree.dll

Stub for the common language runtime engine

Mscoree1_0.dll

Just in time (JIT) and code engines

Netcf_setup.dll

DLL helped for CAB file installation

Netcfagl1_0.dll

Native code portion of Windows.Forms

System.dll

Base class libraries

Mscorlib.dll

Base class libraries

System.xml.dll

XML Reader, writer and DOM support

System.Data.dll

ADO.NET dataset support

System.drawming.dll

GDI drawing support

System.windows.forms.dll

Forms package

System.Web.Services.dll

Web Service client support

Microsoft.VisualBasic.dll

Visual Basic .NET runtime library

System.Net.IrDA.dll

Infrared Communications

Microsoft.PocketPC.dll

Pocket PC specific controls and functionality

Microsoft.WindowsCE.Forms.dll

Windows CE.NET controls

System.Data.Common.dll

Common database connections. As a separate file this helps with memory restrictions

System.Data.SQlClient.dll

Connection to remote SQL Server databases

System.Data.SQlServerCE.dll

Connections to the local SQL Server CE database

System.SR.dll

Detailed exception strings

Calendar_1_0.nlp

Optional calendars

Charinfo_1_0.nlp

Unicode category information

Culture1_1_0.nlp

Invariant culture and English based cultures

Culture2_1_0.nlp

Chinese, Japanese and Korean data parsing functions

Culture3_1_0.nlp

Additional culture information

Building Compact Framework Applications

Figure 4  Creating a new Smart Device project.

 

Compact Framework applications are built using the Visual Studio 2005 smart device application template as shown in Figure 4. 

Figure 5 A new Smart device project

 

Once selected the Smart Device project template creates the mobile device project as shown in Figure  5. By default the Smart Device project references the Compact Framework namespaces shown in Table  2.

 

Table 2: Default namespace references for Smart Device projects

Namespace

Description

System

The System namespace contains the base classes that define commonly-used value and reference data types, events and event handlers, interfaces, attributes, and processing exceptions.

 

System.Drawing

The System.Drawing namespace provides access to GDI+ basic graphics functionality.

System.Windows.Forms

The System.Windows.Forms namespace contains classes for creating form based applications.

 


Figure 6 Visual Studio 2005 supports rotation of devices

Initially the Pocket PC and Smart Phones had a single screen size. Today, devices support portrait, landscape and square screen formats with many starting to provide dynamic display changes. In order to design application effectively the Visual Studio IDE enables both device rotation and visualization as part of the application design experience. This enables developers to see how their mobile application displays at run time. For example, as shown in Figure 6 the device display can be rotated by right clicking the device image and selecting rotate device.

Figure 7 Selecting the device skin properties

 

Technically, an XML based skin file definition is used to define the display of the mobile device in the IDE. Skin definitions are stored as part of the Visual Studio system options as shown in Figure 7. The device skin as shown in Listing 1 consists of an XML definition that defines a set of graphic images and hardware definitions. When displayed in the IDE the hardware definitions are used to define a set of button actions based on a set of mapping colors defined in the graphic images.

 

Listing 1: The XML skin file for a Windows Mobile 5 Pocket PC Phone

<?xml version="1.0" encoding="utf-8" ?>

<skin>

    <view

            titleBar ="Pocket PC Phone - WM 5.0"

           

            displayPosX="55"

            displayPosY="66"

           

            displayWidth="240"

            displayHeight="320"

 

            displayDepth="16"

            mappingImage="pocket_pc_pe_emulator_mask.png"

            normalImage="pocket_pc_pe_emulator_up.png"

            downImage= "pocket_pc_pe_emulator_down.png">

 

        <button

                  toolTip="Power"

                  onPressAndHold="0x75"

                  mappingColor="0x487710"

            />

        <button  

                  toolTip="Record"

                  onPressAndHold="0x44"

                  mappingColor="0xB1AC20"

            />

        <button

                  toolTip="Rocker Up"

                  onPressAndHold="0x48"

                  mappingColor="0x11B997"

            />

        <button

                  toolTip="Rocker Down"

                  onPressAndHold="0x50"

                  mappingColor="0x1BB997"

            />

        <button

                  toolTip="App Launch 1"

                  onClick="DOWN:0x5B 0x70 UP:0x5B"

                  mappingColor="0x5CF443"

            />

        <button

                  toolTip="App Launch 2"

                  onClick="DOWN:0x5B 0x71 UP:0x5B"

                  mappingColor="0xF79406"

            />

        <button

                  toolTip="Soft Key 1"

                  onClick="0x3B"

                  mappingColor="0xDC2C1E"

            />

        <button

                  toolTip="Soft Key 2"

                  onClick="0x3C"

                  mappingColor="0xF699F5"

            />

        <button

                  toolTip="Up"

                  onPressAndHold="0x48"

                  mappingColor="0x3BF8FF"

                  KeyEvent="Up"

            />

        <button

                  toolTip="Down"

                  onPressAndHold="0x50"

                  mappingColor="0x80B9BB"

                  KeyEvent="Down"

            />

        <button

                  toolTip="Left"

                  onPressAndHold="0x4B"

                  mappingColor="0x323DC6"

                  KeyEvent="Left"

            />

        <button

                  toolTip="Right"

                  onPressAndHold="0x4D"

                  mappingColor="0x8E3BFF"

                  KeyEvent="Right"

            />

        <button

                  toolTip="Enter"

                  onClick="0x1C"

                  mappingColor="0xFB10F8"

                  KeyEvent="Return"

            />

        <button

                  toolTip="Talk"

                  onPressAndHold="0x3D"

                  mappingColor="0xFFF601"

            />

        <button

                  toolTip="End"

                  onPressAndHold="0x3E"

                  mappingColor="0x6AAF7"

            />

    </view>

</skin>

 


Figure 8 The mapping art file for a Windows Mobile 5 device.

 

Within the XML definition the <view> element identifies the image files used to display the skin. The normal image element defines the art file that represents the default appearance of the emulator skin within the IDE. The mapping image element as shown in Figure 8 contains the art file that defines the color code for each hardware button. A color code is represented in the mapping file as a single image area that completely covers the individual hardware button. The down image element contains the art file that displays the appearance of the device with each of the hardware buttons pressed. At design time the interaction of the XML definition and graphic images creates the displayed emulator skin.

Designing Mobile Applications

Designing a CF application is different than a Windows desktop application. Table 3 shows many of the device based considerations. Fundamentally, running on a mobile device means that applications are small and portable. CF based applications accept user input and interactions from touch screens, stylus and keypads instead of keyboards. Applications are displayed on small screens instead of nineteen inch monitors. Given both the device limitations and network considerations ensuring a consistent user experience is one the most important parts of the mobile design process.

 

Table 3: Design decisions for mobile devices.

Consideration

Design Goal

CPU Cycles

Mobile devices have limited CPU. This slows the parsing of information being sent to the device and the speed at which the device encodes encrypted communication.

Latency

Most mobile devices implement a power saving protocol. Additionally, there are regulations that set a limit on the Specific Absorption Rate (SAR). The SAR is a measure of the biological effect of a radio frequency emitting device to ensure that cellular phones and other mobile devices are safe. Both of these result in increased latency on devices.

Throughput

General Packet Radio Services (GPRS) mobile devices are available with theoretical maximum speeds of 171.2 kilobits per second. Most phones still use circuit switched data (9.6 Kbps) technologies. This means that mobile devices are affected by protocol overhead and the amount of data being sent.

Unknown network connectivity

A mobile device can go from a full coverage zone to no coverage. Environmental factors will have a direct effect on the quality of the network coverage.

 

Requirements analysis is an important aspect of mobile UI design because it gives an overview of the types of application inputs and outputs.This includes ensuring that the design is appropriate for the form factor and that the application is usable within the required scenarios. Typically the design process is started by prototyping various screens and charting the flow of the application information. For example, many desktop applications launch most actions from a main menu. Based on device screen limitations large menus are not very functional in mobile environments. Mobile applications are task based, with the user moving from screen to screen as each required action is completed.

 

With any mobile user interfaces it is important to pay attention to the amount of data and actions you place on one screen. Given the smaller screen size and limited input makes it almost impossible to incorporate all of an applications’ functionality into a single screen. A good design pattern is better to break up information and actions across several screens. At the same time, it is important to keep mobile applications and their interfaces as concise as possible. For example, if you have a large number of screens, it can become very difficult and frustrating for an application user to easily navigate within the limited framework of the mobile environment.

 

Unlike a desktop application mobile applications have limited real estate. It is important to remember to check with users and monitor application performance. Also, it isn’t uncommon to optimize for specific devices or form factors. Even though the Compact Framework runs on any Windows Mobile device it may make sense to adjust your application to new form factors as they become needed for specific scenarios. The combination of the CF and the Visual Studio design environment helps to design applications with these factors in mind.

Managing Device Form Factors


Figure 9 The form factor property page

 

The original Pocket PC had a default screen resolution of 240 x 320 pixels. A number of the Pocket PCs available today have a different screen resolutions or even square screen. To help ensure this you can set the FormFactor Property as shown in Figure 9.


Figure 10 Setting the default mobile form factor.

 

The FormFactor property is a design time only value. This means that it won’t affect the application itself. It is used to set a number of different screens dimensions for a device, so that the user interface can be verified on the device. Once the new form factor is selected this will display a new device within the designer as shown in Figure 10.

Figure  11 Changing the device target

 

For managed application that target both the Pocket PC and Smartphone, the Visual Studio 2005 user interface is device aware and fully understands the difference in screen and control capabilities between the two devices. Additionally, the designer automatically adjusts when the target platform is changed so that only the available controls that work with the current selected device are shown. Selecting Project – Change Target Platform provides the dialog as shown in Figure 11 to initiate the switch. When switching from one device to another the designer updates the form to the Smartphone designer and offers the appropriate substitution for form controls that are not supported by the Smartphone.

Figure 12 Unsupported control on a Smartphone project

 

There are a number of controls that are not supported by Smartphones. You can distinguish controls that are not supported by the targeted platform because they appear on the form with a warning indicator and their properties are grayed out. Visual Studio 2005 can help you convert unsupported controls to supported controls. When you select an unsupported control in the form and click the arrow shown at the top of the control, a popup menu is displayed with controls that are supported and have comparable functionality as the unsupported control as shown in Figure  12. In the case of buttons Visual Studio helps to convert them to either text boxes or menu items. If you change a button to a menu item, the menu item will be hooked up to the original button_Click event, meaning that the menu item gets the same functionality as the button in a Pocket PC. Both the SaveFileDialog and OpenFileDialog controls are not supported on a Smartphone. But these components are different from buttons—there is no simple conversion from these components to alternative Smartphone controls, so you have to do some work to change these controls.

Docking and Anchoring

Figure 13 Anchoring controls to a CF project.

 

Like the Windows Forms controls, Compact Framework controls implement anchoring and docking to simplify the orientation and location of controls across multiple screen resolutions and orientations. Anchoring designates that a control remains a fixed distance from the edge of a form. As the form size or orientation changes, the position of the control is adjusted to remain the same distance from the form’s edge. Implemented as part of the control properties it is set as shown in Figure 13. By default, controls can be anchored to one or more of the form’s edges.

Figure 14 Setting the control dock

 

Docking a control designates that the control aligns itself directly against the form’s edge and that the control occupies the entire edge. Good UI design creates controls in a stacked effect against the edge of a form using docking. As the user rotates the screen, a docked control automatically adjusts to occupy the designated edge as shown in Figure 14.

Splitter Control

The splitter control enables the resize of the docked control that is located immediately before it in the docking order. Splitter controls are added at design time and this give the form designer the ability to set individual control sizes. The order in which they are added determines the way the splitter control resizes the control. Because there is no way to manually set the docking order, add the splitter control immediately after adding the docked control that is to be resized. It is also important to make sure to dock the splitter control to the edge of the docked control that you want to resize.

 

Figure 15 Using the splitter interface

 

The user interface in Figure 15 is created in the following way. A picture box was added and docked to the form. After that a splitter was added and then docked. Looking at the user interface in the designer view, it may appear that the picture box on the right side of the form can be resized in a horizontal direction only, and the picture box on the left side can be resized both in horizontal and vertical directions.

 

Figure 16 Splitter control occupies as much space as possible

 

However, as you can see in Figure 16 when you move the horizontal splitter, all of the controls will be modified according to the location of the splitter. This behavior is caused by the fact that the lower right picture box is docked to the right edge of the form. The picture box is always trying to occupy as much space as is available on the right edge of form.

Setting Tab Order


Figure 17 A basic mobile interface

 

Tab order is used to determine which control gets focus and can accept keyboard input. It is called tab order because you can change focus from control to control using the TAB key on the keyboard or the soft input panel on a Pocket PC. Tab order determines the order in which users will enter data. For example, in Figure 17 the most natural data entry experience for a user is to navigate from the top to the bottom of the form. Tab order is an important aspect of the usability of a mobile application.


Figure 18 Setting the tab order control properties

 

By default a controls tab order is controlled through the property sheet as shown in Figure 18. This is done by setting the control as a tab stop and then setting the tab index order. For developers this means having to constantly verify a control’s tab orders as new controls are added or moved around on a form.

 

Figure 19 The layout bar

 

Visual Studio 2005 provides a visual designer for tab stops. This is done using the Tab Order button on the layout toolbar as shown in Figure  19. Once selected as shown in Figure 20 you can simply click each control that has the ability to receive input focus to change its tab order.

 

Figure 20 Visually defining the tab order

 

Visual Form Inheritance


Figure 21 An inheritable base form

 

Designing a base form and then using visual inheritance allows the application designer to reuse and extend CF forms. Figure 21 shows an example of CF form that can be inherited. The base form contains an image and a publicly modifiable drop down list. Inheritance is implemented by adding a new CF form to the project. By default the new form is inherited from the System.Windows.Forms.Form. To derive the visual interface from the base form - add the following declaration.

 

Public Class Form1 : Inherits BaseFrm

 

 

Figure 22 The inherited form

 

When you look at the form in design view, you can see the controls from the base class form have been added as shown in Figure 22. The Visual Studio IDE identifies inherited controls by the symbol in the upper left hand corner of the control.

 

Visual Studio also provides an Inheritance Picker Wizard. Once the form is built and the application is compiled you can inherit this form into a newly created form using these steps.

Figure 23 Adding the inherited form

 

  1. Add new item and select the inherited form as shown in Figure 23.

 


Figure 24 Selecting the form to inherit from

 

  1. Select the form to inherit from as shown in Figure 24.

 


Figure 25 The inherited form

 

Once selected the form is added to the project as shown in Figure 25. You can host any control in the base form, as long as you want to reuse it in derived forms. It is important to make sure that you change the modifiers property of the control to protected or public in order to modify the behavior of the particular control in a derived from.

Compact Framework Namespaces

Figure  26 The CF object model

 

Namespaces are used to organize classes and code. The Compact Framework like the desktop framework organizes itself into namespaces as shown in Figure 26. As discussed earlier the goal was to share a common namespace structure with the desktop framework when it made sense. With the limitations of mobile devices the CF object model contains only a subset of the actual full framework. Given the usage patterns of these devices many of the server namespaces like ASP.NET were removed. Additionally, in order to reduce the actual footprint and size of the CF it was designed to support only C# and VB.NET. For example, Windows CE specific extensions in the Compact Framework are defined in a unique namespace that is not used by the desktop framework. The Microsoft.WindowsCE.Forms namespace ships in the Microsoft.WindowsCE.Forms.dll library which contains: a MessageWindow class for sending messages to managed code, the Message structure for use with the MessageWindow Class and InputPanel a wrapper class for the Pocket PC Software Input Panel (SIP).

The System Namespace

The System namespace is the root namespace for fundamental types in the .NET Framework. This namespace is the root of the inheritance hierarchy and contains fundamental classes and base classes that define commonly used values and reference data types, events and event handlers, interfaces attributes and processing exceptions. Still other classes provide support data type conversion method parameter manipulation, mathematics, remote and local program invocation, application environment management and supervision of managed and unmanaged applications.

 

One of the functions of this namespace is the ability to interact with the local file system through the System.IO namespace.  This namespace contains the types that allow synchronous and asynchronous reading and writing of data streams and files. By definition a file is an ordered and named collection of a particular sequence of bytes having persistent storage. Files are defined in terms of directory paths, disk storage and file and directory names. In contrast, streams provide a way to read and write bytes to and from a backing store that can be one of several storage mediums. Just as there are several backing stores other than disks, there are several kinds of streams other than files. For example, there are network, memory and tape streams. For example if we create a CF based word processor application. Listing 2 shows the code to save the contents of a text file to a disk location using the SaveFileDialog.

Listing 2: Saving a text file to a mobile device.

  Private Sub SaveNote()

        Try

            With DlgSaveNote

                .Filter = "Text files (*.txt)|*.txt|All files|*.*"

                .FilterIndex = 1

                If .ShowDialog() = Windows.Forms.DialogResult.OK Then

 

Using sw As StreamWriter = New _ StreamWriter(.FileName)

                        sw.WriteLine(TxtNote.Text.ToString)

                        sw.Close()

                    End Using

                End If

 

            End With

        Catch ex As Exception

            MsgBox(ex.Message, MsgBoxStyle.Exclamation, Me.Text)

        End Try

    End Sub

 

We can then retrieve and open the file using the OpenFileDialog control as shown in Listing 3.

Listing 3: Opening a file from the local file system.

Private Sub MnuOpenNote_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MnuOpenNote.Click

        Try

            With DlgOpenNote

                .Filter = "Text files (*.txt)|*.txt|All files|*.*"

                If .ShowDialog = Windows.Forms.DialogResult.OK Then

                    Try

                 Using sw As StreamReader = New _   

                   StreamReader(.FileName)

                         TxtNote.Text = sw.ReadToEnd

                         sw.Close()

                        End Using

                    Catch fileException As Exception

                        Throw fileException

                    End Try

                End If

 

            End With

        Catch ex As Exception

            MsgBox(ex.Message, MsgBoxStyle.Exclamation, Me.Text)

        End Try

    End Sub

 

 

The System.Web Namespace

 

The CF System.Web namespace contains the classes and interfaces that enable browser-server communication. This namespace includes the HTTPRequest class which provides extensive information about the current HTTP request, the HTTP response class which manages HTTP output to the client and the HTTPServerUtility class which provides access to server side utilities and process.


Figure 27 Setting the Web Service reference.

 

One of the primary features of the Compact Framework is the ability to consume and interact with Web Services. This can be done both synchronously and asynchronously. Synchronous Web Service calls are simple to code, but may cause the application to appear to freeze if the Web Service is unresponsive. Asynchronous calls however allow the user to continue to interact with the application while the call to the Web Service is going.

 

When making synchronous calls to the Web service, the calling thread is blocked until the Web Service returns the results of the method call. Synchronous calls are useful if the method you are calling on the server does not require much processing time and will return quickly. In addition synchronous Web Service calls are simpler to implement. To make a synchronous call to the Web Service, you create an instance of the proxy class and then call the methods and within the proxy class as you would with any other class. For example within a Compact Framework application you can set the Web Service reference to the Invoices Web Services as shown in Figure 27. Once the Web reference is set you can make s synchronous call and then bind the returned dataset to a DataGrid using the code in Listing 4.

 

*** Note***
When setting the Web Reference with the Compact Framework make sure to use either the URL or IP address. The Compact Framework doesn’t recognize the use of locahost.

 

Listing 4: Making a synchronous call to a Web Service.

  Dim ds As New DataSet

        Dim ws As New wsInvoices.Invoices

        ds = ws.GetAllCustomers

 

        With CmbCustomers

            .DisplayMember = "customerid"

            .DataSource = ds.Tables(0)

        End With

 

***Note***

When consuming a Web Service from a Smart Device project there is an initial delay on the first call. This is the result of the CF setting up the initial connection details for the Web Service and caching the details.

 

An asynchronous Web Service call allows the continued use of the calling thread while you wait for the Web Service to respond. This means users can continue to interact with the running application until the Web Service responds. This is a better design pattern and makes more effective use of threads. An asynchronous call is made on a different thread than the one that is running the user interface. Web Service application don’t require any special configuration or modification support for asynchronous operations. By default for every synchronous method in the proxy class there is a corresponding Begin and End asynchronous method calls. For example if the name of a Web Service method is Getitems, the asynchronous methods are BeginGetItems and EndGetItems. Calling Web Services asynchronously is a two step process. First call the Begin method to initiate the call to the Web Service. Secondly, call the End method to complete the Web Service call and retrieve the response from the Web Service.

 

The Begin method returns a System.Web.Services.Protocol.WebClientAsyncResult object which implements the System.IASyncResult interface. This object provides status information about the pending asynchronous call. For example Listing  5 shows how to call the BeginGetInvoices asynchronous method for a selected customer.

Listing  5: Starting an asynchronous Web Service call.

If CmbCustomers.Text <> "" Then

            Dim ds As New DataSet

            Dim ws As New wsInvoices.Invoices

            Dim wcb As New AsyncCallback(AddressOf wsReturn)

            Dim ar As IAsyncResult = ws.BeginGetCustomerInvoices(CmbCustomers.Text, wcb, ws)

 

        End If

 

There are several ways to determine when an asynchronous Web Service call is completed.

  • Pass a callback delegate to the Begin method. The callback delegate executes when the Web Service call completes.
  • Force the application to wait using one of the WaitHandle methods of the IAsyncResult.AsyncWaitHandle object. When using the methods of the WaitHandle, the client application can also specify a timeout which it will abandon waiting for results from the Web Service it called.
  • Poll the value of the IasynResult.IsCompleted property in your main thread code for a value of true, call the End method to retrieve the response from the Web Service.

 

The most efficient method is passing a callback delegate to the Begin method. By default, callback functions don’t block threads while waiting for a response. When the Web Service returns its response the callback delegate executes in a new thread. Then simply call the End method inside the callback as shown in Listing 6.

 

Listing 6: Retrieving the results of an asynchronous Web Service call.

Private Sub wsReturn(ByVal ar As IAsyncResult)

        ' Get the completed results

        Dim ws As wsInvoices.Invoices = ar.AsyncState

        ads = ws.EndGetCustomerInvoices(ar)

 

        'Create an EventHandler delegate.

        Dim updateUI As New EventHandler(AddressOf BindGrid)

        Invoke(updateUI)

    End Sub

 

When calling a Web Service asynchronously the Begin method takes the following parameters.

BeginGetItems(callback as System.AsyncCallback, asyncState as object)

 

 

The first parameter is an asyncCallback object which is created by passing the address of the ServiceCallback method in its constructor. The second parameter is the type object. You can pass any object that will assist you in handling the response from the Web Service. You can access the same object by getting the AsyncState property of the IAsyncResult parameter to your callback method. It is important to remember that when calling a Web Service asynchronously, the call executes on a separate thread from the user interface. The invoke method is the way to merge the returned data back to the main thread. For example, Listing  7 shows how to bind the results of an asynchronous call to a data grid.

Listing 7: Binding to a DataGrid from an asynchronous Web Service call.

Private Sub BindGrid(ByVal sender As System.Object, ByVal e As System.EventArgs)

        With DataGrid1

            .DataSource = ads.Tables(0)

        End With

    End Sub

The System.XML Namespace

The System.XML namespace provides the foundation support for classes that work with XML data. The System.XML classes contain a comprehensive set of XML classes for parsing, validating and manipulating XML data for readers, writers and World Wide Web Consortium (W3C) DOM compliant components.

Figure  28 Adding an XML document to a mobile project

 

For example, if we add an XML document to a device project as shown in Figure 28. This file can then be used to add catalog information as shown in Figure 29. Listing 8 shows the code needed to read the content of the file into a combo box.

Figure 29 A populated XML file.

 

Listing 8: Reading an XML file

Private Sub LoadCatalogItems()

        Dim AppPath As String = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase) & "\" & "catalog.xml"

 

        Dim catItems As New XmlDocument

        catItems.Load(AppPath)

 

        ' Create an XmlNamespaceManager to resolve the default namespace.

        Dim nsmgr As XmlNamespaceManager = New XmlNamespaceManager(catItems.NameTable)

        nsmgr.AddNamespace("it", "urn:catlog-items")

 

        ' Select and display the catalog items

        Dim nodeList As XmlNodeList

        Dim root As XmlElement = catItems.DocumentElement

        nodeList = root.SelectNodes("/it:catalog/it:catalogItem/it:itemname", nsmgr)

        Dim title As XmlNode

        CmbItems.BeginUpdate()

        For Each title In nodeList

            CmbItems.Items.Add(title.InnerXml)

        Next

        CmbItems.EndUpdate()

End Sub

 

When an item is selected in the list box we can use the code in Listing 9 to retrieve the selected nodes from the XML file.

Listing 9: Retrieving the selected XML node.

Private Sub CmbItems_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CmbItems.SelectedIndexChanged

        Dim AppPath As String = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase) & "\" & "catalog.xml"

 

        lblcost.Text = ""

        lbldescription.Text = ""

 

        Dim catItems As New XmlDocument

        catItems.Load(AppPath)

 

        ' Create an XmlNamespaceManager to resolve the default namespace.

        Dim nsmgr As XmlNamespaceManager = New XmlNamespaceManager(catItems.NameTable)

        nsmgr.AddNamespace("it", "urn:catlog-items")

 

        ' Select and display the catalog items

        Dim nodeList As XmlNodeList

        Dim root As XmlElement = catItems.DocumentElement

        nodeList = root.SelectNodes("descendant::it:catalogItem[it:itemname='" & CmbItems.Text & "']", nsmgr)

        Dim title As XmlNode

 

        For Each title In nodeList

            lbldescription.Text = title.ChildNodes(1).InnerXml

            lblcost.Text = "$" & title.ChildNodes(2).InnerXml

        Next

 

    End Sub

 


Figure 30 The selected XML Node.

 

When selected this returns the catalog item detail as shown in Figure  30.

The System.Data Namespace

The System.Data namespace provides access to classes that represent the ADO.NET architecture. ADO.NET lets you build components that manage data from multiple data sources. The centerpiece of the desktop .NET Framework ADO.NET architecture is the Dataset class. Each Dataset class can contain multiple DataTable objects, with each DataTable containing data from a single source such as SQL Server. For example, the Web Service code within Listing 10 returns a Dataset.

Listing 10: Returning a DataSet from a Web Service

<WebMethod()> Public Function GetCustomerInfo(ByVal CustomerID As String) As DataSet

        Dim oSQLConn As SqlConnection = New SqlConnection

        oSQLConn.ConnectionString = "Data Source=THOMSPC;Initial Catalog=Northwind;Integrated Security=SSPI"

        oSQLConn.Open()

 

        Dim sqlcomm As New SqlCommand

        With sqlcomm

            .Connection = oSQLConn

            .CommandType = CommandType.Text

            .CommandText = "Select * From customers where customerid='" & CustomerID & "'"

        End With

 

        Dim SQLDA As New SqlDataAdapter(sqlcomm)

        Dim ds As New DataSet

        With SQLDA

            .Fill(ds)

        End With

 

        Return ds

    End Function

 

 

Using the System.Data.SqlClient, System.Data.Odbc, System.Data.OleDb, or the System.Data.OracleClient namespace you can access a data source to use together with a DataSet. Each.NET Framework data provider has a corresponding DataAdapter that you use as a bridge between a data source and a DataSet. Each DataTable contains a DataColumnCollection. This is a collection of DataColumn objects that are used to determine the schema of each DataTable. The DataType property determines the type of data held by the DataColumn. If a DataTable participates in a parent/child relationship with another DataTable, the relationship is constructed by adding a DataRelation to the DataRelationCollection of a DataSet object. When such a relation is added, a UniqueConstraint and a ForeignKeyConstraint are both created automatically, depending on the parameter settings for the constructor. The UniqueConstraint guarantees that values that are contained in a column are unique. The ForeignKeyConstraint determines what action will happen to the child row or column when a primary key value is changed or deleted.

 

Accessing SQL Server Mobile

Microsoft SQL Server 2005 Mobile Edition is the CF based database for rapidly developing applications that extend enterprise data management capabilities to mobile devices. SQL Server Mobile is designed to integrate with the Compact Framework through Visual Studio 2005. This helps to simplify the development process for building database applications with the .NET Framework.

 

SQL Server Mobile supports Structured Query Language (SQL) syntax and providing a development and API consistent with SQL Server. The System.Data.SqlServerCe namespace provides the functionality you must have to program .NET applications that use SQL Server Mobile. For example, the code in Listing 11 can be used to create and then check a SQL Mobile Database on the device.

 

Listing 11: Creating and checking a SQL Mobile database

     ' create the database

        Dim sqlDB As String = "Orders.sdf"

        If System.IO.File.Exists(sqlDB) Then

            File.Delete(sqlDB)

        End If

 

        Dim connString As String = "Data Source='Orders.sdf'; LCID=1033; Password=""testit""; Encrypt = TRUE;"

        Dim engine As New Data.SqlServerCe.SqlCeEngine(connString)

        engine.CreateDatabase()

 

        ' check the database

        Dim vengine As New Data.SqlServerCe.SqlCeEngine("Data Source = Orders.sdf; Password=testit")

 

        If False = vengine.Verify() Then

            MessageBox.Show("Database is corrupted.")

            vengine.Repair(Nothing, Data.SqlServerCe.RepairOption.RecoverCorruptedRows)

        End If

 

The SQL Server Mobile engine exposes a basic set of relational database features such as an optimizing query processor and support for transactions and data types while keeping a minimal footprint for mobile devices. SQL Server Mobile supports the following data types as shown in Table 4.

 

Table 4: SQL Server Mobile supports the following data types

Data Type

Description

Storage Size

Bigint

Integer (whole number) data from –2^63 (–9,223,372,036,854,775,808) through 2^63–1 (9,223,372,036,854,775,807).

8 bytes

Integer

Integer (whole number) data from –2^31 (–2,147,483,648) through 2^31–1 (2,147,483,647).

4 bytes

smallint

Integer data from –32,768 to 32,767.

2 Bytes

Tinyint

Integer data from 0 to 255

1 Byte

Bit

Integer data with a value of either 1 or 0.

1 Byte

numeric (p, s)

Fixed-precision and scale-numeric data from –10^38+1 through 10^38–1.

19 Bytes

Money

Monetary data values from (–2^63/10000) (–922,337,203,685,477.5808) through 2^63–1 (922,337,203,685,477.5807

8 Bytes

Float

Floating point number data from –1.79E +308 through 1.79E+308

8 Bytes

Real

Floating precision number data from –3.40E+38 through 3.40E+38.

4 Bytes

datetime

Date and time data from January 1, 1753, to December 31, 9999, with an accuracy of one three-hundredth second, or 3.33 milliseconds. Values are rounded to increments of .000, .003, or .007 milliseconds.

Stored as two  byte integers. The first 4 bytes store the number of days before or after the base date, January 1, 1900. The other 4 bytes store the time of day represented as the number of milliseconds after midnight.

national character(n)

Synonym:nchar(n)

Fixed-length Unicode data with a maximum length of 4000 characters.

Storage size in bytes is two times the number of characters entered.

national character varying(n)

Synonym:nvarchar(n)

Variable-length Unicode data with a length of 1 to 4000 characters.

Storage size in bytes is two times the number of characters entered.

Ntext

Variable-length Unicode data with a maximum length of (2^30–2)/2 (536,870,911) characters.

Storage size in bytes is two times the number of characters entered.

binary(n)

Fixed-length binary data with a maximum length of 8000 bytes.

 

Storage size is fixed, which is the length in bytes declared in the type

varbinary(n)

Variable-length binary data with a maximum length of 8000 bytes.

Storage size is the length of the declared value in bytes.

Image

Variable-length binary data with a maximum length of 2^30–1 (1,073,741,823) bytes.

Storage is the length of the value in bytes.

uniqueidentifier

A globally unique identifier (GUID).

16 Bytes

IDENTITY [(s, i)]

This is a property of a data column, not a distinct data type.

Only data columns of the integer data types can be used for identity columns. A table can have only one identity column. If a seed and increment are specified the column cannot be updated.

N/A

ROWGUIDCOL

This is a property of a data column, not a distinct data type. It is a column in a table that is defined by using the uniqueidentifier data type. A table can have only one ROWGUIDCOL column.

N/A

 


Figure 31 Adding a SQL Mobile database

 

It is also possible to add a SQL mobile database to a project using the Add New Items as shown in Figure 31. Once added to the project you can create a typed dataset. Within device projects Datasets tend to consume a great deal more resources. When working with local databases the SQLCEResultSet provides an updateable, scrollable, and bindable cursor for local databases.

. They can be created using the following steps.

  1. Add a SQL Mobile data source to the project using the TableAdapter Wizard

 


Figure 32 Setting the custom tool to return a SQLCEResultSet.

 

  1. In the properties of the generated XSD modify the value of the customer tool value to MSResultSetGenerator as shown in Figure 32.

 

After completing the above steps the project now contains a typed SQLCEResultSet.

***Note***

If an application requires both a typed DataSet and a typed SQLCeResultSet use the custom tool MSDataSetResultGenerator.

 

The benefit of the SQLCeResultSet is that it can be accessed using the same exact method as using a dataset. For example, to bind the results to a DataGrid use the code shown in Listing 12.

Listing 12: Binding a SQLCEResultSet to a DataGrid.

'using the SQLCE Result set

        Dim sa As New OrdersResultSet

 

        With DataGrid1

            .DataSource = sa

        End With

 

It additionally exposes methods that allow the direct update of records as shown in Listing 13.

 

Listing  13: Adding records to the SQL Mobile database.

Dim ins As New Orders.OrdersResultSet

        ins.AddOrdersRecord(txtCustomer.Text, OrderDate.Text, TxtOrderAmt.Text)

        ' clear the order

        ResetOrder()

        ' refresh the grid

        ViewRecords()

Application Domains in the CF

Traditional Windows based development has considered the process as the basic unit of execution and isolation for running applications. The basic theory was that each running application was loaded into a separate process that automatically isolated each application from others. If for example, an error occurred in a single application, that wouldn’t affect the others running on the system. Essentially, a process defined a security boundary that also prevented applications from talking directly with each other. This actually worked quite well and helped to solve the perpetual tug of war that existed between scalability and fault tolerant systems. With the advent of the .NET runtime this concept was enhanced to include a new type of entity called the Application Domain. Much like the process, the Application Domain is designed as a security boundary that confines errors and faults to a specific domain.

Figure 33 Application Domain Model for CF

 

 

As shown in Figure 33 every .NET CF application runs inside a runtime construct called an application domain, which is similar to the operating system process. The CF ensures that all managed resources used by a running application are freed or returned to the host operating system when the application ends. Application domains offer many advantages of processes, such as fault isolation and security without requiring support from an underlying host operating system. An application domain starts an instance of the common language runtime and is itself native operating system code. The common language runtime can be statically or dynamically linked to the application domain host.

 

 

Although, it is similar to the process, the Application Domain has somewhat different characteristics. By design the Application Domain is considered to be much lighter than the traditional Windows based process. Ideally, Application Domains are perfect for application scenarios that require isolation without the heavy overhead associated with the traditional application process. Also, by the definition discussed above, the process runs exactly one application. Of course this is contrast to the Common Language Runtime (CLR) within the .NET Framework that enables multiple applications to run within a single process. The Framework accomplishes this by loading each application into a separate Application Domain and verifying that all user code in an Application Domain is considered type safe.

 

The Application Domain is designed as a virtual process that serves to isolate applications. By default each .NET Framework application within an Application Domain runs under the control of a host that creates and loads the assemblies. This guarantees that each application is independent and isn’t able to directly access resources within another domain. The application host is then able to access evidentiary information like the code loading location, digital signatures, and version of any application code that it loads. This evidence is what the Common Language Runtime uses to make decisions when applying the security policy. Each bit of evidence indicates to the runtime that code has a particular characteristic. Based on the supplied evidence both the assemblies and Application Domains receive a set of permission grants.

 

Inside the Framework

Within the actual Framework, the System.AppDomain class provides the Application Domain functionality used by the hosts. An Application domain, which is represented by AppDomain objects, helps to provide the necessary isolation for unloading and security boundaries managed code execution. Multiple Application Domains are able to run in a single process. However, there isn’t a one to one correlation between application domains and threads. Several threads can belong to a single Application Domain. While a given thread is not confined to a single application domain, at any given time, a thread executes in a single application domain.

 

The Windows operating system does not directly provide support for running a CLR application. That support is provided by a CLR host. A CLR host is an application that is responsible for loading the CLR into a process, creating application domains within the process, and executing user code within the application domains. Application domains are created using the CreateDomain method from within one of the possible application hosts as shown in Table 5. AppDomain instances are used to load and execute assemblies. Once the AppDomain is no longer used, it can be unloaded. The AppDomain class implements a set of events that enables applications to respond when an assembly is loaded, unloaded or when an unhandled exception is thrown.

 

Table  5 Types of application hosts

Application Host Type

Description

Custom designed hosts

A managed or native code application that creates a domain and loads assemblies. For example, the Compact Framework is instantiated this way.

Browser Host

Domains created within the context of a web site. For example, an ISAPI filter ships with ASP.NET.

Shell Host

Launches applications from the shell. When a managed application is launched from a shell, a piece of unmanaged code loads the CLR and transitions control of the application to the CLR.

 

Once an application domain is created the host provides the ability to specify a security policy that is applied to code that runs within the Application Domain. This security policy is always subject to the any of the pre-defined policies. For obvious security reasons a host does have the ability to reduce a specific set of permissions but can’t by default grant additional permissions it doesn’t already have. Policy can be set only once for an Application domain. In order to set Application domain policy the host must be granted the security permissions that is provided through the SecurityPermission class for controlling domain policy. After an application domain policy is set, all subsequently loaded assemblies are granted permissions under the new policy. However, any previously loaded assemblies derive their permission grants under the pre-existing policy. By default, the permissions granted to these assemblies are not reevaluated under the new application domain policy.

 

A trusted host can provide information or evidence to the runtime about assemblies that are loaded into the application domain. If a domain host does not have the appropriate SecurityPermission for controlling evidence, the runtime uses the security enforced on the host to determine the security to enforce on the assembly.

 

In some situations, evidence that would normally be provided by a trusted application domain host is actually provided by the loader. Typically, after an application domain is created, the application domain host loads the first (main) assembly into the application domain and calls into that assembly to begin execution. When code in the first assembly references code in another assembly, the loader resolves the reference, loads the appropriate assembly into the application domain, and supplies the evidence about the assembly to the runtime. In this situation, the trusted application domain host that provided the evidence for the original assembly does not provide evidence to subsequently loaded assemblies.

 

The CF doesn’t place restriction on the behavior of the application host. The application domain host can be a simple extension to an existing interactive shell that is used to start and stop programs. On dynamic applications systems like Windows, the application domain host can be an extension to the application loader so that the .NET Compact Framework applications can be started and stopped using the same mechanism as native applications.

 

The CF supports multiple application domains. Developers can specify an assembly in the constructor of a class. Then you can use the CreateDomain method to start a new application domain. The new application domain loads its own copies of the common language runtime DLLs, data structure and memory pools. Multiple application domains can exist in one operating system process. Each application domain exposes a set of properties. These properties are used to identify the current domain. For example, the following code will retrieve the friendly name of the current application domain.

 

Dim dName As String = AppDomain.CurrentDomain.FriendlyName

 

***Note***

The .NET Compact Framework does not support loading assemblies into a domain neutral code area for use by multiple application domains.

 

The AppDomainSetup Class is used to provide the common language runtime with configuration information for a new Application Domain. Probably the most important thing to keep in mind when creating Application Domains is setting the ApplicationBase property. This directory location serves as the application root and identifies the starting point for the assembly manager when looking for other assemblies. Once set, this property cannot be changed after the Application Domain has finished loading. It is always important to keep in mind that this location can directly influence which permissions are granted to an Application Domain. For example, an Application Domain that originates on the local machine automatically receives full trust. However, if the ApplicationBase is set to the path of an Intranet directory, the default settings will restrict the permission set to the permission set granted to the local Intranet.

 

***Note***

Always keep in mind that that any new Application Domains will by default only inherit the ApplicationBase property of its creator.

 

For example, the code in Listing 14 creates a new Application Domain when a button is clicked within a Windows Form application.

Listing  14: Creating a new Application Domain

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        ' Create application domain setup information.

        Dim MyDomainInfo As New AppDomainSetup

        MyDomainInfo.ApplicationBase = "C:\testapp"

 

        ' Create the application domain.

        Dim domain As AppDomain = AppDomain.CreateDomain("MyNewDomain", Nothing, Mydomaininfo)

 

        ' Show Application domain information

        MsgBox("Application base is: " + domain.SetupInformation.ApplicationBase)

        MsgBox("Host domain: " + AppDomain.CurrentDomain.FriendlyName)

        MsgBox("child domain: " + domain.FriendlyName)

 

        ' Unload the application domain.

        AppDomain.Unload(domain)

 

    End Sub

The Application Domain that is created is parented to the current running application. However, it operates as a separate entity that can be shut down and controlled independent of the current application. The .NET Compact Framework determines when garbage collection should b e run. Garbage collection can occur in a single application domain or in all application domains. This prevents one application domain for using too much memory at the expense of others.

The Visual Studio 2005 Emulators

Emulators allow you to test your application on different types of target platforms without needing to actually have the devices. Emulators play a very important part of the development cycle. By default applications are automatically deployed to an emulator when run from the Visual Studio environment.

 

Figure 34 Selecting the emulator that is used to deploy the application

 

For example, once the project is created and you press F5 to debug the applications you are asked to select a device to deploy to as shown in  34.

There are three ways to start the Device Emulator from Visual Studio 2005

  1. From Tools-Connect To Device- Select emulator-Connect
  2. From Tools- Device Emulator Manager, then right click on any emulator from the displayed list and press ‘Connect’.
  3. Create a smart device project and either press F5 or Deploy Solution. Select an emulator prompted.

 

***Note***

If you are deploying an application onto the emulator for the first time it may take a while for the application to load. This is because Visual Studio 2005 is installing the .NET Compact Framework 2.0 class libraries onto the device.

 

Figure 35 The Device Emulator Manager

 

The Device Emulator Manager is the easiest way to activate and manage emulator images. Within the Device Emulator Manager, you can right-click on the emulator that you want to launch and select Connect as shown in Figure  35. The selected emulator then is launched.

 

***Note***

Visual Studio 2005 running on the desktop interacts with the device emulator using a direct memory access (DMA) channel.

 

Once the emulator is running you can then select cradle to synchronize the emulator with the local desktop environment using ActiveSync. The Synchronization Setup Wizard appears and you can synchronize your device with the local computer. Once the emulator is connected to ActiveSync, you can explore the file system on the emulator by clicking the Explore button in ActiveSync.

Summary

The Compact Framework is an important element in building mobile applications. It contains a similar metaphor as the desktop framework but with some important differences. In this article we looked at some of the key things to consider when building mobile applications for the Compact Framework.