随笔 - 27  文章 - 4 评论 - 45 trackbacks - 0
<2006年8月>
303112345
6789101112
13141516171819
20212223242526
272829303112
3456789


与我联系

常用链接

留言簿(2)

我参与的团队

随笔分类

随笔档案

文章分类

文章档案

收藏夹

技术站点

日常站点

设计站点

搜索

  •  

最新评论

阅读排行榜

评论排行榜

  现在在公司的一个项目中使用到AtlasToolkit中的CacadingDropDown,有一些需要有多选框(即Asp.Net服务器控件中的ListBox,HTML代码中的<select multiple="true"></select>),但是CascadingDropDown并不支持多选,全部是单选. 经过一翻研究和尝试之后,终于给它增加了多选的功能,于是就有了这篇文章.

  AtlasToolkit中的控件由几个部分组成

  •   Bihavior:这是一个客户端Js文件,定义了控件在客户端的行为,应该是AtlasTookit控件的核心部分
  •   Extender:这是控件的服务端支持,用于支持控件的服务端操作
  •   Properties:这是服务端配置类
  •   Designer:设计时支持

 在开始之前,先看看效果(注意最下一行字,这就是多选的结果),

要改造CascadingDropDown,就要拿这几个部分分别开刀.现在一步一步来.

第一步,使它在服务端支持ListBox

  虽然多选框跟单选下拉框在客户端都是Select,但在服务端却是两个不同的控件.CascadingDropDown本身只支持DropDownList

public class CascadingDropDown : ExtenderControlBase<CascadingDropDownProperties, DropDownList>

  上面是Extender文件中CascadingDropDown的声明,它继承自ExtenderControlBase,注意红色部分,因为这里的声明使它仅仅支持DropDownList,现在我们要把它改成ListControl,这样就可以同时支持ListBox和DropDownList了,因为这两个都继承自ListControl.

除了这里,Properties和Designer中的相应的泛型声明都要改成ListControl.

  以上做的是在接口上支持ListBox,现在要使它在行为上支持ListBox.这个只需要改Extender一个文件就可以了.

 

protected override void OnLoad(EventArgs e)
{
 base.OnLoad(e);
 foreach (CascadingDropDownProperties cascadingDropDownProperties in TargetProperties)
 {
  ListControl ctrl = (ListControl)FindControlHelper(cascadingDropDownProperties.TargetControlID);
  if (ctrl is DropDownList)
  {
   DropDownList dropDownList = ctrl as DropDownList;
   dropDownList.Items.Clear();
   dropDownList.Items.Add(cascadingDropDownProperties.ClientState);
  }
  else if (ctrl is ListBox)
  {
   ListBox listBox = ctrl as ListBox;
   listBox.Items.Clear();
   if (cascadingDropDownProperties.ClientState == null)
    return;
   foreach (string item in cascadingDropDownProperties.ClientState.Split(','))
   {
    listBox.Items.Add(item);
   }
  }
 }
}

protected override void OnPreRender(EventArgs e)
{

 foreach (CascadingDropDownProperties cascadingDropDownProperties in TargetProperties)
 {
  ListControl ctrl = (ListControl)FindControlHelper(cascadingDropDownProperties.TargetControlID);
  if (ctrl is DropDownList)
  {
   DropDownList dropDownList = ctrl as DropDownList;
   dropDownList.Items.Clear();
  }
  else if (ctrl is ListBox)
  {
   ListBox listBox = ctrl as ListBox;
   listBox.Items.Clear();
  }
 }

 base.OnPreRender(e);
}

  好了,上面就是改变服务端的,使之确实地支持ListBox,到这里服务端就修改完成了.

第二步,修改Behavior,以下的修改后的Behavior文件中的set_SelectedValue, 只需要修改这个地方就可以了.

 

this.set_SelectedValue = function(value) {

if( this.control != null && this.control.element != null && this.control.element.multiple )
{
  var e = this.control.element;
  //是多选框,即ListBox
  _selectedValue = new Array();
  for( var i = 0; i < e.options.length; ++i )
  {
   if( e.options[i].selected )
     _selectedValue[ _selectedValue.length ] = e.options[i].value;
  }
  AtlasControlToolkit.CascadingDropDownBehavior.callBaseMethod(this, 'set_ClientState', [ _selectedValue.toString() ]);
}
else
{
  _selectedValue = value;
  AtlasControlToolkit.CascadingDropDownBehavior.callBaseMethod(this, 'set_ClientState', [ _selectedValue ]);
}
}

  好了,编译,控件的发行就完成了.接下来说使用.

  第一步:把ASPX文件中的DropDownList改成ListBox,并且加上SelectMode="Multiple"

  第二步:使用类似以下的代码来取值

 

foreach (ListItem item in DropDownList3.Items)
{
//if (item.Selected)
color += RemoveValueText(item.Value) + ","
}

  注意,我把红字部分,这一行是不需要的,因为传回来的所有Item都是被选中的,没有被选中的项并没有被传回来.

posted @ 2006-08-26 11:28 Lupin 阅读(1467) | 评论 (6)编辑

tags: , , , ,

  昨天才知道有ActionPack这个东西,据介绍说很多概念是从Ruby On Rails来的,但我对Ruby On Rails没有了解,所以也不知道是怎样,但我知道ActionPack真是是相当强的东西,即使它现在还不是足够的强大,但是经过发展,必然大有作为.

  闲话少说,到底ActionPack是个什么东西呢.说白了,它就是一个代码生成器,帮你生成访问数据库的代码. 但跟一般的代码生成器又有不同,ActionPack生成的代码并不存储在文件系统中,而是直接被编译在内存中,连Dll文件都没有.

  它是怎么做到这些的呢?

  最核心的就是BuildProvider了,它使用了Framework中的BuildProvider,在在生成的时候动态编译代码.这被编译的这些代码就是根据数据库中的表来生成的.而要让它做到这些,你只需要在配置文件中配置数据库连接字符串就可以了.

  以上是感性的认识,接下来看看它的结构.

  首先是一个BuildProvider,它继承自System.Web.Compilation.BuilderProvider,只要在Web.Config文件中配置,就可以让它在生成的时候直接运行里面的GenerateCode方法,跟HttpHandler有点类似.这是触发点.

  然后是CodeGeneration,看名字就明白了,它用来生成代码.

  然后是SchemaService,这个是用来读取数据库中的表信息的

  TableSchema,存放表信息,在进行代码生成的时候使用到.

  上面这几个,是ActionPack实现机制的主要部分.接下来的是一些配置和数据库访问的东西

  ActionPackConfig,ActionPackConfigurationSetting,这两个是读取配置文件的,比较简单.

  DBHelper和Query这两个是数据库操作的

  ActiveList,ActiveRecord,这两上是Entry的模板类.在这里封装DBHelper和Query中的操作,使用这两个模板类,使生成的代码变得十分简单.否则,生成代码的工作将变得十分繁琐.

ActionPack的结构就这样了,有空再继续深入剖析.

posted @ 2006-08-26 11:14 Lupin 阅读(177) | 评论 (1)编辑