您的位置:资讯频道 > 技术文档 > 控件使用经验谈

Mobile Web Application中的TextArea控件开发

来源:个人博客   作者:sharetop   时间:2007-12-21  点击:625 次

      在用 VS.NET 做移动 WEB 开发时,很明显有一个控件是非常有用但是 VS.NET 却没有提供的,那就是 TextArea,多行输入.
 
      开发一个自定义控件,要自己实现两个类,一是派生于某个控件的你想要的控件类,二是负责将这个控件 Render 出来的适配器类(Adapter).
 
      首先,我们实现一个叫 MultiLineTextBox 类,派生于 TextBox 类,比较简单,就是多了两个属性 Cols 和 Rows.代码如下:
 public class MultiLineTextBox : System.Web.UI.MobileControls.TextBox
 {
 
  private int _cols=0;
  public int Cols
  {
   get{ return this._cols; }
   set{ this._cols=value; }
  }
  private int _rows=0;
  public int Rows
  {
   get{ return this._rows; }
   set{ this._rows=value; }
  }
 }
 
      当然你也可以象老外文章那样,直接把两个属性值放在 ViewState 中,如果你不打算在你的程序中禁用 ViewState 的话,这应该是一个更好的办法.
 
      第二步,实现一个派生于 ControlAdapter 的 MultiLineTextBoxAdapter 类,重载一个属性和一个方法即可.代码如下:
public class HTMLMultiLineTextBoxAdapter : System.Web.UI.MobileControls.Adapters.ControlAdapter
 {
  protected new MultiLineTextBox Control
  {
   get  {  return (MultiLineTextBox)base.Control;   }
  }
 
  public override void Render(HtmlTextWriter writer)
  {
   writer.WriteBeginTag("textarea");
     
   String renderName;
   if(Device.RequiresAttributeColonSubstitution)
   {
    renderName = Control.UniqueID.Replace(':', ',');
   }
   else
   {
    renderName = Control.UniqueID;
   }
   writer.WriteAttribute("name", renderName); 
   writer.WriteAttribute("cols",Control.Cols.ToString());
   writer.WriteAttribute("rows",Control.Rows.ToString());
     
   writer.Write(">");
   writer.Write(Control.Text);
   writer.WriteEndTag("textarea");

  }
 }
 
      属性 Control 的重载说明我要管理的类叫 MultiLineTextBox.而重载的 Render 方法则具体了如何在页面中去表现这个控件,就是输出一个 textarea 标签.
 
      第三步,找到 web.config 中的 MobileControls 段落.修改成以下模样:
 
<mobileControls cookielessDataDictionaryType="System.Web.Mobile.CookielessData"  >
 <device name="htmlDeviceAdapters" inheritsFrom="HtmlDeviceAdapters" >
   <control name="cn.sharetop.model.comm.MultiLineTextBox,cn.sharetop.model"
    adapter="cn.sharetop.model.comm.HTMLMultiLineTextBoxAdapter,cn.sharetop.model"/>       
 </device> 
</mobileControls>
 
      第四步, 当然就是应用了,在你的 Asp 页面中,这样使用这个控件,先声明前缀和名域空间,以及程序集:
 
<%@ Register TagPrefix="myControl" Namespace="cn.sharetop.model.comm" Assembly="cn.sharetop.model" %>

然后,在页面加入我们自己的多行输入控件:
 
 <mobile:form id="Form1" runat="server">
  <FONT face="宋体">&nbsp;
   <myControl:MultiLineTextBox id="mtextbox1" runat="Server" Cols="20" Rows="6" Text="me"></myControl:MultiLineTextBox>
  </FONT>
 </mobile:form>
 
      OK,现在你用 IE 访问这个 web application,会发现这个控件被正确解析成了<textarea>.
 
      至此,我们的工作算是成功了一半.
 
      但是马上你就会发现,为什么用手机访问根本没有变化,仍是一个单行输入的<input>,......我尝试了Openwave 7 和 Openwave 6.2 两个 WAP 模拟器,以及 Nokia 6680和 Sumsung X859两款手机,都不能得到想要的结果...
 
      从模拟器可以看出,在 Openwave 6.2 中,IIS 返回的 ContentType 是 application/xhtml-xml,而 Openwave 7中,却返回了 text/vnd.wap.wml.....奇怪啊奇怪...
 
      我就是在这点被卡住了,呵呵,主要是对 web.config 的配置不熟,里面的那些东西都是停留在"知其然,不知其所以然"的阶段...没办法,只好再 Google 了...
 
      我的机器安装了 DeviceUpdate 4. 为了找出问题所在,我打开 deviceupdate4.config 和  machine.config 两个文件...经过仔细研究,也算是明白了个大概吧...
 
      在 web.config 中增加的那个 device 段中有一个 inheritsFrom="HtmlDeviceAdapters",我开始以 为这是一个类,结果在 MSDN 中却没找到,呵呵...原来它是定义在 machine.config 中的一个段落...说明,我现在 web.config 中 定义的 htmlDeviceAdapters device 来自于 machine.config 中的 HtmlDeviceAdapters...而在 HtmlDeviceAdapters 中定义了各种 控件的实现,原来如此....
 
      在 machine.config 中我发现了许多与 xhtml 相关的内容,都是 update 4 增加进去了,既然 IIS 对 Openwave 6.2 返回是 xhtml 的类型,那问题估计就出在这里了,我应该再增加一下针对 xhtml 的 device,让它也去找我定义的新控件,于是,我把 web.config 改成以下样子:
<mobileControls cookielessDataDictionaryType="System.Web.Mobile.CookielessData"  >
 <device name="xhtmlLDeviceAdapters" inheritsFrom="XhtmlDeviceAdapters" >
  <control name="cn.sharetop.model.comm.MultiLineTextBox,cn.sharetop.model"
  adapter="cn.sharetop.model.comm.HTMLMultiLineTextBoxAdapter,cn.sharetop.model"/>
 </device>
 <device name="wmlDeviceAdapters" inheritsFrom="WmlDeviceAdapters" >
  <control name="cn.sharetop.model.comm.MultiLineTextBox,cn.sharetop.model"
  adapter="cn.sharetop.model.comm.HTMLMultiLineTextBoxAdapter,cn.sharetop.model"/>  
 </device>
 <device name="htmlDeviceAdapters" inheritsFrom="HtmlDeviceAdapters" >
   <control name="cn.sharetop.model.comm.MultiLineTextBox,cn.sharetop.model"
    adapter="cn.sharetop.model.comm.HTMLMultiLineTextBoxAdapter,cn.sharetop.model"/>
 </device> 
</mobileControls>
 
      定义三个device段落,分别来自于HtmlDeviceAdapters,XhtmlDeviceAdapters和WmlDeviceAdapters,让这三种设备都使用我们定义的MultiLineTextBox控件...
 
      终于,我在两个模拟器和我的 X859上都正确看到想要的结果了....说明现在,IIS 对 Html 的设备,Xhtml 的设备,以及 Wml 的设备都允许使用这个自定义控件了...
 
      但是,还有一个问题,为什么我的 Nokia 6680,却仍不能显示呢?
 
      继续,在 deviceupdate4.config 中,我找到了针对 nokia 手机的设备定义,有3650却没有6680,这个好办,改吧,其 实这两款手机差不多的,都是 S60平台,屏幕也一样大...于是我新增了一个6680设备,内容就与3650一样即可...OK 了,我的 Nokia 6680也可以看到这个多行输入框了...同样道理,为什么 Openwave 7的 wml 也可以通过这个方式修正...不过我没做,因为我需要一个 wml 的设备.
 
      这件事的解决过程中,我走了一些弯路....也记下来,以警示自己!!!
 
      1.当我发现 IIS 返回 WML 的时候,我尝试了让这个控件的 Adapter 直接派生于 WmlTextBoxAdapter,并且,修改了 web.config 中的 inheritsFrom 为 WmlDeviceAdapters,在 Openwave 7中成功,于是我想让 IIS 针对所有设备都输出 WML...真是太直了...我把 pageAdapter 都设成 wmlPageAdapter 了...结果 IE 一访问,咣当弹出一个下载对话框,....呵呵....
 
      2.我一直以为,我可以在代码中强制输出的类型,结果发现不行,IIS 判断设备,并响应合适的 ContentType,不需要由代码控制的,全在两个 config 中配置(只是这两个 config 也太复杂了)......