The Mobile Internet Toolkit comes prepackaged with a variety of controls
that address the most common mobile computing tasks. However, specialized
tasks can arise that these generic controls are not powerful enough to
address, or for which they simply fail to meet the requirements. In these
cases it is beneficial to develop a custom control that is suited to
fulfilling the required tasks.
In this article, I will concentrate on developing and implementing such
custom controls within a mobile application. The primary focus will not be
on creating custom user controls and/or inherited controls since these can
be created for the Mobile Internet Toolkit in much the same way as a
standard ASP.NET control. Rather, I will focus on creating custom controls
from scratch so I can address some of the unique issues of mobile Internet
development. Before I begin, it is essential that you understand exactly how
a mobile Web control operates.
How ASP.NET Mobile Controls Function
ASP.NET controls are in a sense a hybrid of traditional Windows form
controls and HTML controls. Standard HTML controls are able to furnish a
graphical interface component that can be loaded into a browser window via
an HTTP protocol, but they require that all forms of state management be
handled manually. ASP.NET controls overcome this limitation by moving the
graphical component of HTML controls to a server-based component that
manages properties and states. This means that each time the client calls
the control, the fields are not reinitialized to their default value.
Rather, the values stored in these fields from the previous instance of the
control are maintained. This basic architecture is shared by mobile ASP.NET
controls, with one big difference. The ASP.NET control architecture is
centered around delivering HTML to browser clients. This type of layout is
not suitable for extending functionality to the diversity of mobile devices
that the Mobile Internet Toolkit targets. For instance, HTML might be
acceptable for a Pocket PC running Microsoft's Pocket Internet Explorer, but
it would do little to facilitate display on a WML-enabled phone.
For this reason, mobile controls place calls to device-specific adapter
classes, which in turn output the appropriate markup for the type of browser
detected by the Mobile Internet Toolkit runtime. Client requests are routed
to an instance of a control class to handle all device-independent logic and
one instance of a device adapter class to handle device-specific rendering
and any other desired device-specific functionality (see Figure 1). If you
are coding inherited controls you do not always need to create
device-specific adapters, since the adapter functionality inherited from the
parent control is often adequate. However, in order to make any custom
control that you write (i.e., from scratch) compatible with the wealth of
devices supported by the Mobile Internet Toolkit, you will need to code at
least two types of device-specific adapters an HTML adapter class and a
WML adapter class. Other device adapters can also be coded to implement
cHTML or other types of markups.
In order to get a better feel for how these device adapters function, I
will develop a simple custom control and its required device adapters and
develop a specialized label. Of course, more exquisite functionality is
possible (e.g., custom events, methods, etc.), but these techniques are
beyond the scope of the article, and are common to the development of almost
all types of controls under the .NET Framework. The control I develop here
will be a specialized label that might be used by doctors to check on their
patients from anywhere in the hospital by accessing a mobile Web page that
will display patient information on their mobile device. This control will
display the patient's name, room number, and status.
To start a mobile Internet controls project, you create a Web Control
Library project, just as you would to start an ASP.NET controls project, and
then add a reference to System.Web.Mobile.dll, which provides access to
classes in the System.Web.UI.MobileControls namespace. The Web Control
Library wizard will create a default class, WebCustomControl1, which
inherits from System.Web.UI.WebControls.WebControl. When you create a mobile
control, you need to change the base class to MobileControl. Since mobile controls use device-adapter classes to handle client rendering, you can also delete the Render method provided by the wizard.
After making those changes I begin to lay out the device-independent
logic of the control, which in this case amounts to the code that will
create three properties: the patient's name, room number, and status. I will
call these properties Pname, Room, and Status, respectively. After defining
these properties my code looks like Listing 1.
It's not always necessary to create controls from scratch like I did
here. If your desired control parallels the functionality of an existing
control closely enough, like a numeric text box versus a normal text box,
inheritance may actually be a better option. If I had been developing an
inherited control I would have inherited from a preexisting class like
TextBox that defines the control of interest. The remainder of the code lays
out the three string properties that the control will utilize.
Since I'm building a custom control I now have another task: developing
the device-specific adapter classes. If I were inheriting from another
control I probably wouldn't need to do this. In many cases the device
adapters that are made available through the inheritance of the parent
control are sufficient.
Now that I have my label control I'd like to be able to render it to
HTML, just like I would in ASP.NET. To do this for mobile controls I create
a class I'll call CLHTMLAdapter that inherits from the HTMLControl
Adapter class in the System.Web.UI.MobileControl.Adapter namespace. HTMLControlAdapter contains useful functionality for sending HTML to the client.
The next step is crucial in the development of device adapters all
device adapters must have a strongly typed property called Control. This
will return an object that is typed to the control class that will work with
this adapter. The .NET Framework uses this property to associate device
adapter classes with the appropriate control class.
Finally, I need to write a Render method on my adapter class. Since I
chose to inherit from HtmlControlAdapter I need to override its Render
function, which takes an HtmlMobileTextWriter as an argument. Different
Adapter classes define their Render methods slightly differently, but they
all take an instance of a MobileTextWriter-derived class. I've summarized
the most commonly used methods in this class in Table 1. For my control I
will write out the patient's name, room number, and status, as shown in
Listing 2.
Now that my HTML adapter is done, my control will be visible from
browsers but not from cell phones, pagers, or other WML devices. To enable
access from these devices, I create a second device-adapter class, derived
from WmlControlAdapter, as shown in Listing 3.
As you can see, the WML device adapter is structured in much the same
way as the HTML device adapter. This time my Render method uses the passed
WmlMobileTextWriter to create WML-based markup to send to the client. It is
important to note that after calls to EnterStyle or EnterLayout the
RenderText method must be employed rather than a Write method, since the
Enter methods of the WMLMobileTextWriter are unable to render tags. Instead
they just indicate in what format tags should be output upon rendering. WML
does not offer the same range of possibilities as HTML, something you should
take into account in your display design.
Now that I've authored my control and some Adapter classes, I compile
them into an assembly together. Controls and adapters don't necessarily need
to be compiled into the same assembly, but for simplicity I just compiled
them into an assembly named CustomLabel.
Now I'm ready to use my custom control in a mobile Web application. I
start by using the Mobile Web Application Project wizard and adding a
reference to CustomLabel.dll. Next I edit my WebForm.aspx file by right-clicking on the file in Solution Explorer and selecting Open With, followed by Text Editor. Then I need to add a reference to the control library to the WebForm, as well as embed the control into the page body. I do this by adding these lines, part of Listing 4.
<%@ Register TagPrefix="CustomLabel" Namespace="CustomLabel"
Assembly="CustomLabel" %>
.....
<CustomLabel:CLabel id="CLabel1" runat="server" Status="Stable"
Room="23" Pname="John Doe"></CustomLabel:CLabel>
The <%@ Register %> directive defines the name of the tag that will
represent the control in the ASP.NET page, while the other line of code
defines the default state for the control. In order to refer to control in
the code behind the form (.aspx.cs), you should add a using statement that
points to the control's namespace.
At this point I am almost finished. The last thing to do is to
configure the application to use the new device adapters so that the label
will render properly on different types of clients. ASP.NET uses Web.config
to do this by editing the Web.config file of the application, which is an
XML-based file that stores application and server settings. As a starting
point, find the machine.config file located in Windows/Microsoft .NET/Framework/version/CONFIG and open it in a text editor. Find
the section that runs from <mobileControls> to </mobileControls> and copy it
into the application Web.config file in place of the default line <mobile-
Controls cookielessDataDictionaryType="System.Web.Mobile.CookielessData" />.
This section of the .config file specifies which mobile controls work with
which device adapters. By adding this to the project's Web.config file I can
override the server defaults stored in machine.config and enable the
application to work with my custom device adapters. I will now need to make
the changes and additions highlighted in Listing 5.
You will notice that the highlighted changes all occur within the
<device> ... </device> sections, which define each adapter set. It is
important that each adapter set have a unique name so that the compiler does
not confuse the customized sets with the default sets. Notice that within
the HTML adapter set and the WML adapter set I define the particular adapter
required by the control, using the syntax <control name ="control name,
assembly name" adapter="adapter name, assembly name" />. This defines which device adapters are called for a particular client rendering of the control.
You may have also noticed that the Web.config file defines two other
device adapter sets, one for cHTML and one for UpWML (used for Phone.com
phones). Since I did not develop specific device adapters for these sets I
define them so that they inherit functionality from my customized HTML and
WML device adapter sets. In this way they will utilize the HTML and WML
rendering methods defined for those sets respectively.
Now I am ready to make use of the customized control. To test it out, I
add some values to each of the properties that were laid out and run the
application. Figure 2 demonstrates how it should render on an HTML browser
and Figure 3 shows how a WML-enabled phone should render. As you can see, in
both cases the patient's name, room number, and status are displayed.
This concludes a brief tour of creating customized controls and device
adapters for use with the Mobile Internet Toolkit. By mastering these basic
principles you can unlock the full potential of control customization for
mobile devices of all kinds.
Author Bio
Christopher Frenz is the author of Visual Basic and Visual Basic .NET for
Scientists and Engineers (Apress) and is pursuing his doctorate in
biocomputing. In his current research Christopher uses neural networks to
model biological systems and develops Web-based scientific applications.
cfrenz@att.net
Listing 1: The custom label control class
using System;
using System.Web.UI.MobileControls;
namespace CustomLabel
{
/// <summary>
/// Simple Custom Mobile Control
/// </summary>
///
public class CLabel : MobileControl
{
private string pname, room, status;
public CLabel()
{
Pname="";
Room="";
Status="";
}
public string Pname
{
get
{
return pname;
}
set
{
pname = value;
}
}
public string Room
{
get
{
return room;
}
set
{
room=value;
}
}
public string Status
{
get
{
return status;
}
set
{
status=value;
}
}
}
}
Listing 2: The HTML adapter class
using System;
using System.Web.UI.MobileControls;
using System.Web.UI.MobileControls.Adapters;
using CustomLabel;
namespace CustomLabel.Adapters
{
/// <summary>
/// HTML Adapter for Custom Control
/// </summary>
public class CLHTMLAdapter: HtmlControlAdapter
{
protected new CLabel Control
{
get
{
return(CLabel)base.Control;
}
}
public override void Render(HtmlMobileTextWriter
writer)
{
writer.EnterStyle(Style);
writer.WriteLine("Patient: " + Control.Pname + "</p>");
writer.WriteLine("<p> Room: " + Control.Room + "</p>");
writer.WriteLine("<p> Status: " +
Control.Status);
writer.ExitStyle(Style);
}
}
}
Listing 3: The WML Adapter Class
using System;
using System.Web.UI.MobileControls;
using System.Web.UI.MobileControls.Adapters;
using CustomLabel;
namespace CustomLabel.Adapters
{
/// <summary>
/// WML Adapter for Custom Control
/// </summary>
public class CLWMLAdapter: WmlControlAdapter
{
protected new CLabel Control
{
get
{
return(CLabel)base.Control;
}
}
public override void Render(WmlMobileTextWriter
writer)
{
writer.EnterStyle(Style);
writer.RenderText("Patient: " + Control.Pname);
writer.WriteLine("</p>");
writer.Write("<p>");
writer.RenderText("Room: " + Control.Room);
writer.WriteLine("</p>");
writer.Write("<p>");
writer.RenderText("Status: " + Control.Status);
writer.ExitStyle(Style);
}
}
}
Listing 4: Edited WebForm.aspx
<%@ Register TagPrefix="CustomLabel" Namespace="CustomLabel"
Assembly="CustomLabel" %>
<%@ Page language="c#" Codebehind="MobileWebForm1.aspx.cs"
Inherits="MobileWebApplication2.MobileWebForm1" AutoEventWireup="false" %>
<%@ Register TagPrefix="mobile" Namespace="System.Web.UI.MobileControls"
Assembly="System.Web.Mobile, Version=1.0.3300.0, Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a" %>
<meta name="GENERATOR" content="Microsoft Visual Studio 7.0">
<meta name="CODE_LANGUAGE" content="C#">
<meta name="vs_targetSchema"
content="http://schemas.microsoft.com/Mobile/Page">
<body Xmlns:mobile="http://schemas.microsoft.com
/Mobile/WebForm">
<mobile:Form id="Form1" runat="server">
<CustomLabel:CLabel id="CLabel1" runat="server"
Status="Stable" Room="23" Pname="John
Doe"></CustomLabel:CLabel>
</mobile:Form>
</body>
Listing 5
<mobileControls
sessionStateHistorySize="6"
cookielessDataDictionaryType="System.Web.Mobile.CookielessData">
<!-- applications which inherit the cookielessDataDictionaryType can disable it
by setting it to an empty string "" -->
<device
name="CustomHtmlDeviceAdapters"
predicateClass="System.Web.UI.MobileControls.Adapters.HtmlPageAdapter"
predicateMethod="DeviceQualifies"
pageAdapter="System.Web.UI.MobileControls.Adapters.HtmlPageAdapter">
<control
name="System.Web.UI.MobileControls.Panel"
adapter="System.Web.UI.MobileControls.Adapters.HtmlPanelAdapter" />
.
.
.
<control
name="System.Web.UI.MobileControls.MobileControl"
adapter="System.Web.UI.MobileControls.Adapters.HtmlControlAdapter" />
<control
name="CustomLabel.CLabel,CustomLabel"
adapter="CustomLabel.Adapters.CLHTMLAdapter,CustomLabel" />
</device>
<device
name="CustomUpWmlDeviceAdapters"
inheritsFrom="CustomWmlDeviceAdapters"
predicateClass="System.Web.UI.MobileControls.Adapters.UpWmlPageAdapter"
predicateMethod="DeviceQualifies"
pageAdapter="System.Web.UI.MobileControls.Adapters.UpWmlPageAdapter">
</device>
<device
name="CustomWmlDeviceAdapters"
predicateClass="System.Web.UI.MobileControls.Adapters.WmlPageAdapter"
predicateMethod="DeviceQualifies"
pageAdapter="System.Web.UI.MobileControls.Adapters.WmlPageAdapter">
<control
name="System.Web.UI.MobileControls.Panel"
adapter="System.Web.UI.MobileControls.Adapters.WmlPanelAdapter" />
.
.
.
<control
name="System.Web.UI.MobileControls.MobileControl"
adapter="System.Web.UI.MobileControls.Adapters.WmlControlAdapter" />
<control
name="CustomLabel.CLabel,CustomLabel"
adapter="CustomLabel.Adapters.CLWMLAdapter,CustomLabel" />
</device>
<device
name="CustomChtmlDeviceAdapters"
inheritsFrom="CustomHtmlDeviceAdapters"
predicateClass="System.Web.UI.MobileControls.Adapters.ChtmlPageAdapter"
predicateMethod="DeviceQualifies"
pageAdapter="System.Web.UI.MobileControls.Adapters.ChtmlPageAdapter">
.
.
.
</device>
</mobileControls>
All Rights Reserved
Copyright © 2004 SYS-CON Media, Inc.
E-mail:
info@sys-con.com