天天看点

[Wap] 制作自定义WmlListAdapter来实现Mobile.List控件的各种效果

编写者

日期

关键词

郑昀@ultrapower

2005-8-18

wap asp.net mobile control device adapter

现有的mobile.list输出效果,每一个item之间一定会换行,如果你看了wmllistadapter的源代码就知道了,这是因为他们在输出每一个item渲染时调用了renderlink(writer, item.value, null, false, false, item.text,true);,最后一个参数就是是否在本item渲染后输出换行标记。

我们可以改变这种渲染方式,从而让mobile.list变成横排效果。

现有的mobile.list输出效果,每一个item前后无法插入一张image。

我们可以改变这种渲染方式,从而让mobile.list变成可以自定义每一行的插入图片效果。

总的效果如下图所示:

[Wap] 制作自定义WmlListAdapter来实现Mobile.List控件的各种效果

可以参考我的上一篇文章《[wap]编译adapter来自定义mobile control》,http://www.cnblogs.com/zhengyun_ustc/archive/2005/07/28/customcuildyourmobilecontrol.html。

下面,我们来介绍一下步骤:

在这里我们新建一个类库项目,叫做“listadapter”,它将生成一个listadapter.dll,我们的自定义控件以及adapter就在这个dll中。

在这个项目中,我们将定义一个继承自

system.web.ui.mobilecontrols.adapters.wmllistadapter

的adapter,来准备改写mobile:list控件的输出方式。

将下面的代码保存为listadapter.cs:

<b>listadapter.cs</b><b></b>

using system.web.ui;

using system.web.ui.mobilecontrols.adapters;

using system.web.ui.mobilecontrols;

namespace ultrawmladapter

{

    public class imagelist : system.web.ui.mobilecontrols.list

    {

        private string _img="";

        public string image

        {

            get{ return this._img; }

            set{ this._img=value; }

        }

    }

    public class wmlimglistadapter :system.web.ui.mobilecontrols.adapters.wmllistadapter

    { 

        protected new imagelist control

            get

            {

                return (imagelist)base.control;

            }

        public override void render(

            wmlmobiletextwriter writer)

            log.debugtrace("imglistadapter render begin:"

                + this.control.uniqueid);

            if(control.hascontrols())

                writer.begincustommarkup();

                renderchildren(writer);

                writer.endcustommarkup();

                return;

            int pagestart = control.firstvisibleitemindex;

            int pagesize = control.visibleitemcount;

            if (pagesize == 0)

            /*

                 * 我们在上面自定义了image属性,那么这里我们可以通过control.image来获取它,

                 * 在aspx页面上,它可能是这么定义的,&lt;cc1:imagelist image="images/5.gif" &gt;&lt;/cc1:imagelist&gt;;

                 * 这样,我们就可以直接通过control.image获取字符串"images/5.gif"。

                 * zhengyun_ustc 20050819

                 *

                 */

            string strlistimageurl = (string)control.image;

            if(strlistimageurl != null

                &amp;&amp; strlistimageurl.length &gt; 0)

                writer.writebegintag("img");

                writer.writeattribute("src", strlistimageurl);

                writer.writeline(" /&gt;");

            system.web.ui.mobilecontrols.mobilelistitemcollection items = control.items;

            if (items.count == 0)

            bool itemsaslinks = control.itemsaslinks;

            bool hascmdhandler = control.hasitemcommandhandler;

            writer.enterstyle(style);

            for (int i = 0; i &lt; pagesize; i++)

                system.web.ui.mobilecontrols.mobilelistitem item = items[pagestart + i];

                /*

                 * 请注意这里不能用breakafter的名字作为本item的customattributes,

                 * 因为好像和原先的breakafter冲突;所以这里的customattributes名字最好都起一个

                 * 比较特殊的,不与原先mobile:list的属性们冲突!

                string strbreakafter = (string)item.customattributes["breakafteritem"];

                // 默认都换行!

                bool bbreakafteritem = true;

                if(strbreakafter != null

                    &amp;&amp; strbreakafter.length &gt; 0)

                {

                    strbreakafter = strbreakafter.tolower();

                    switch(strbreakafter)

                    {

                        case "false":

                            // 要求渲染时不换行

                            bbreakafteritem = false;

                            break;

                        default:

                    }

                }

                if (itemsaslinks)

                    renderlink(writer, item.value, null, false, false, item.text, bbreakafteritem);

                else if (hascmdhandler)

                    renderpostbackevent(writer, item.index.tostring(), null,true, item.text, bbreakafteritem);

                else

                    writer.rendertext(item.text, bbreakafteritem);

                 * 我们知道mobilelistitem有一个customattributes成员,它

                 * “returns the set of custom attributes defined for the control.”

                 * 也就是说我们通过"item.customattributes",可以得到当前这个control的自定义属性的集合;

                 * 这样如果我们这样定义list的某一个item:

                 * &lt;item text="1" value="1" image="images/2.png" breakafteritem="true"&gt;&lt;/item&gt;

                 * 那么可以通过item.customattributes["image"]获取image属性的值;

                string strcurrentlistitemimageurl = (string)item.customattributes["image"];

                if(strcurrentlistitemimageurl != null

                    &amp;&amp; strcurrentlistitemimageurl.length &gt; 0)

                    writer.writebegintag("img");

                    writer.writeattribute("src", strcurrentlistitemimageurl);

                    writer.writeline(" /&gt;");

            writer.exitstyle(style);

            log.debugtrace("imglistadapter render end");

       做一个说明,我们的imagelist类是从system.web.ui.mobilecontrols.list继承下来的,增加了一个image属性作准备。

       另外,自定义的wmlimglistadapter就是继承了

system.web.ui.mobilecontrols.adapters.wmllistadapter,所以我们要重写

render(wmlmobiletextwriter writer)函数,从而让它做到下面两件事情:

通过

<b>web.config</b><b>中的</b><b>system.web</b><b>节点下</b><b></b>

来获取在aspx页面上定义的list自定义属性。这里的知识点就是,你可以在aspx中这么定义&lt;cc1:imagelist id="newlist1" runat="server" image="images/5.gif" &gt;,那么直接就可以通过control.image来获取这个“images/5.gif”字符串。这是当前list控件总的image图片显示。

我们还可以通过在每一个item商定以自定义属性image来在list的每一项后面都输出一张图片。

string strcurrentlistitemimageurl = (string)item.customattributes["image"];

这里的知识点是,mobilelistitem有一个customattributes成员,它代表“returns the set of custom attributes defined for the control.”。也就是说我们通过"item.customattributes",可以得到当前这个control的自定义属性的集合。

所以,如果我们这样定义list的某一个item:

&lt;item text="1" value="1" image="images/2.png" breakafteritem="true"&gt;&lt;/item&gt;

那么可以通过item.customattributes["image"]获取image属性的值了。

编译出一个listadapter.dll,并设置输出路径为你的wap应用程序bin目录下。

在你的wap项目中,添加对lisadapter.dll的引用。

或者你也可以修改web.config,添加如下配置,也能起到相同的作用:

&lt;!--  动态调试编译

          设置 compilation debug="true" 以启用 aspx 调试。否则,将此值设置为

          false 将提高此应用程序的运行时性能。

          设置 compilation debug="true" 以将调试符号(.pdb 信息)

          插入到编译页中。因为这将创建执行起来

          较慢的大文件,所以应该只在调试时将此值设置为 true,而在所有其他时候都设置为

          false。有关更多信息,请参考有关

          调试 asp.net 文件的文档。

    --&gt;

    &lt;compilation defaultlanguage="c#" debug="true"&gt;

        &lt;assemblies&gt;

            &lt;add assembly="listadapter"/&gt;

            &lt;add assembly="multilineinput"/&gt;

        &lt;/assemblies&gt;

    &lt;/compilation&gt;

现在你已经修改了mobile:list控件的最终渲染方式,让我们试试看吧。

新建一个移动web窗体页面“imglist.aspx”,填写如下:

&lt;%@ register tagprefix="mobile" namespace="system.web.ui.mobilecontrols" assembly="system.web.mobile" %&gt;

&lt;%@ page language="c#" codebehind="imglist.aspx.cs"

inherits="ipower.imglist" autoeventwireup="false" %&gt;

&lt;%@ register tagprefix="cc1" namespace="ultrawmladapter" assembly="listadapter" %&gt;

&lt;head&gt;

       &lt;meta content="microsoft visual studio .net 7.1" name="generator"&gt;

       &lt;meta content="c#" name="code_language"&gt;

       &lt;meta content="http://schemas.microsoft.com/mobile/page" name="vs_targetschema"&gt;

&lt;/head&gt;

&lt;body xmlns:mobile="http://schemas.microsoft.com/mobile/webform"&gt;

       &lt;mobile:form id="form1" title="wap测试imagelist控件" runat="server"&gt;

              &lt;cc1:imagelist id="newlist1" runat="server" itemsperpage="0" itemsaslinks="true" breakafter="false"

                     stylereference="title" enableviewstate="false"image="images/5.gif" &gt;

                     &lt;item text="1" value="1" image="images/1.png" breakafteritem="true"&gt;&lt;/item&gt;

                     &lt;item text="2" value="2" image="images/2.png" breakafteritem="false"&gt;&lt;/item&gt;

                     &lt;item text="3" value="3" image="images/3.png" breakafteritem="false"&gt;&lt;/item&gt;

                     &lt;item text="4" value="4" image="images/5.gif" breakafteritem="false"&gt;&lt;/item&gt;

                     &lt;item text="5" value="5" image="images/1.png" breakafteritem="true"&gt;&lt;/item&gt;

              &lt;/cc1:imagelist&gt;

              &lt;mobile:textbox id="input1" runat="server" name="ti" rows="5" cols="25"&gt;&lt;/mobile:textbox&gt;

              &lt;mobile:command id="cmdadditem" runat="server"&gt;添加一个item&lt;/mobile:command&gt;

       &lt;/mobile:form&gt;

&lt;/body&gt;

记得在你的wap项目下,建立一个images目录,并放置图片。

编辑mobile:command的click事件,添加如下代码:

newlist1.items.add(input1.text);

newlist1.items[5].customattributes["image"] = "images//additem.png";

这时候,程序依然无法运行,我们必须修改web.config来告知如何应用我们的自定义imagelist以及adapter。

在你的web.config文件中找到mobilecontrols节点,修改为以下:

&lt;!-- 指定没有 cookie 的数据字典类型

        这将使字典的内容出现在本地请求 url 查询字符串中。

        这是在没有 cookie 的设备上进行窗体身份验证所必需的。

    &lt;!--在您使用像 userandomid 这样的自定义属性时,必须在您的移动 web 应用程序中启用自定义属性allowcustomattributes。

    &lt;mobilecontrols allowcustomattributes="true"cookielessdatadictionarytype="system.web.mobile.cookielessdata" &gt;

        &lt;device name="ultrawmldeviceadapters" inheritsfrom="wmldeviceadapters"&gt;

            <b>&lt;control name="ultrawmladapter.imagelist,listadapter"</b>

<b>              </b><b>adapter</b><b>="ultrawmladapter.wmlimglistadapter,listadapter"</b><b> </b><b>/&gt;</b><b></b>

        &lt;/device&gt;

&lt;/mobilecontrols&gt;

device节点就声明了一个新的adapter,名为“ultrawmldeviceadapters”,这个名字是可以随便定义的。

以后你每增加一个自定义adapter,都必须在这个device节点之下加入一个control,你必须通过name属性提供控件的fully qualified control class name:“<b>ultrawmladapter.imagelist,listadapter</b>”,control的name属性指的是“你重载的哪一个mobile控件”,然后<b>adapter</b>属性指出如何渲染。

这样,重新编译你的工程后,新的渲染方式就生效了。

你可以在m3gate模拟器/opera7.6上试验。

2005-8-19