关于Ext Extender

什么是Ext Extender?
ExtExtenders是由Rodrigo Diniz开发的一组对Extjs 客户端控件的.net服务器端包装控件
由Extender可知道其运行必须ASP.NET AJAX框架的支持.
类似的项目有Coolite,但为什么我们更应该关注ExtExtenders呢? 开源,而且功能更加强大.
演示地址 http://www.extendersamples.qsh.eu/
项目主页 http://www.codeplex.com/ExtJsExtenderControl
开源软件的最大好处就是我们不仅能够利用它来为我们的工作带来方便,而且能够透过其源代码,学习作者的实现方法,
领悟其设计思路,加快我们进步的步伐,正所谓是站在巨人的肩膀上,好风凭借力.

一如往常的技术介绍文章,让我们从最简单的开始,Extjs的日历组件界面美观,功能也非常强大而且没有复杂的服务器端 - 客户端交互行为, 就让我们先拿它开刀吧

首先我们到Codeplex下载一份源代码,这里以版本31017作为示例.
解压好后,先看到GridControl目录下的几个文件: YUI.cs, YUI-ext.cs, ext-yui-adapter.cs .
可以看到这几个文件实现非常简单:就是一个静态类,标注了其需要使用的嵌入式资源.
 1[assembly: System.Web.UI.WebResource("ExtExtenders.yui.js""text/javascript")]
 2namespace ExtExtenders
 3{
 4    /// <summary>
 5    /// Class to include the js file
 6    /// </summary>  

 7    public static class YUI
 8    {
 9    }

10}

然后来到今天的主角Calendar,这个文件夹里分别有CalendarExtenderExtender.cs 和一个脚本文件CalendarExtenderBehavior.js(注意到整个项目里的js和css以及图片文件都设为了嵌入式文件)
看看CalendarExtenderExtender.cs 里到底实现了啥

  1[ToolboxBitmap(typeof(System.Web.UI.WebControls.Calendar))]
  2    public class ExtCalendar : TextBox, IScriptControl
  3    {
  4        private ScriptManager sm;
  5        private string _disabledDays;
  6        /// <summary>
  7        /// An array of days to disable, 0 based. For example, [0, 6] disables 
  8        /// Sunday and Saturday (defaults to null).
  9        /// </summary>

 10        public string disabledDays
 11        {
 12            get
 13            {
 14                return _disabledDays;
 15            }

 16            set
 17            {
 18                _disabledDays=value;
 19            }

 20        }

 21        private string _disabledDaysText;
 22        /// <summary>
 23        /// The message that appears when a date is disabled
 24        /// </summary>

 25        public string disabledDaysText
 26        {
 27            get
 28            {
 29                return _disabledDaysText;
 30            }

 31            set
 32            {
 33                _disabledDaysText=value;
 34            }

 35        }

 36        private string _disabledDates;
 37        /// <summary>
 38        /// An array of "dates" to disable, as strings. These strings will be used to build a dynamic regular expression so they are very powerful.
 39        /// Some examples:  * ["03/08/2003", "09/16/2003"] would disable those exact dates
 40       /// * ["03/08", "09/16"] would disable those days for every year
 41       ///* ["^03/08"] would only match the beginning (useful if you are using short years)
 42        ///* ["03/../2006"] would disable every day in March 2006
 43       ///* ["^03"] would disable every day in every March
 44       ///In order to support regular expressions, if you are using a date format that has "." in it, you will have to escape the dot when restricting dates. For example: ["03\\.08\\.03"].
 45        /// </summary>

 46        public string disabledDates
 47        {
 48            get
 49            {
 50                return _disabledDates;
 51            }

 52            set
 53            {
 54                _disabledDates=value;
 55            }

 56        }

 57        private string _disabledDatesText;
 58        /// <summary>
 59        ///  The tooltip text to display when the date falls on a
 60        /// disabled date (defaults to 'Disabled')
 61        /// </summary>

 62        public string disabledDatesText
 63        {
 64            get
 65            {
 66                return _disabledDatesText;
 67            }

 68            set
 69            {
 70                _disabledDatesText=value;
 71            }

 72        }

 73        private string _format;
 74        /// <summary>
 75        /// The default date format string which can be overriden for localization support. 
 76        /// The format must be valid according to Date.parseDate (defaults to 'm/d/y').
 77        /// </summary>

 78        public string format
 79        {
 80            get
 81            {
 82                return _format;
 83            }

 84            set
 85            {
 86              _format=value;
 87            }

 88        }

 89
 90        /// <summary>
 91        /// Raises the pre render event.
 92        /// </summary>
 93        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>

 94        protected override void OnPreRender(EventArgs e)
 95        {
 96            base.OnPreRender(e);
 97            string resource = Page.ClientScript.GetWebResourceUrl(GetType(), "ExtExtenders.yui-ext.css");
 98            string csslink = "<link href='" + resource + "' rel='stylesheet' type='text/css' />";
 99            Page.Header.Controls.Add(new LiteralControl(csslink));
100            ClientScriptManager man = Page.ClientScript;
101            //render the yui-ext scripts
102            man.RegisterClientScriptResource(typeof(YUI), "ExtExtenders.yui.js");
103            man.RegisterClientScriptResource(typeof(YUI_ext), "ExtExtenders.yui-ext.js");
104            man.RegisterClientScriptResource(typeof(ext_yui_adapter), "ExtExtenders.ext-yui-adapter.js");
105            if (!this.DesignMode)
106            {
107                // Test for ScriptManager and register if it exists
108                sm = ScriptManager.GetCurrent(Page);
109
110                if (sm == null)
111                    throw new HttpException("A ScriptManager control must exist on the current page.");
112
113                sm.RegisterScriptControl(this);
114            }

115           
116        }

117        /// <summary>
118        /// Renders the control to the specified HTML writer.
119        /// </summary>
120        /// <param name="writer">The <see cref="T:System.Web.UI.HtmlTextWriter"></see> object that receives the control content.</param>

121        protected override void Render(HtmlTextWriter writer)
122        {   
123            base.Render(writer);
124            if (!this.DesignMode)
125                sm.RegisterScriptDescriptors(this);
126         
127        }

128       
129        IScriptControl Members
173    }

由声明可知,ExtCalendar直接继承了TextBox,且实现了IScriptControl.
让我们来看看IScriptControl的接口规范, msdn之
1public interface IScriptControl
2{
3    IEnumerable<ScriptDescriptor> GetScriptDescriptors();
4    IEnumerable<ScriptReference> GetScriptReferences();
5}

当一个类实现了IScriptControl,其需要分别实现两个方法.
GetScriptDescriptors()方法用来返回客户端元素是如何与该服务器端控件进行数据交互的Descriptor
GetScriptReferences()方法则告诉ScriptManager在程序运行时需要引入哪些script以及路径.

其后,ExtCalendar声明了一系列对应于Extjs库中Calendar客户端组件的属性. 并且重写了TextBox的OnPreRender方法注册了所需要的客户端资源.
这里需要注意的是,如果我们要使用中文版的ExtCalender的话,需要从Extjs的资源包中拷贝ext-lang-zh_CN.js到项目中设为嵌入式资源并且修改YUI.cs
在类声明上添加[assembly: System.Web.UI.WebResource("ExtExtenders.ext-lang-zh_CN.js", "text/javascript")]

接下来,看看作者是如何实现IScriptControl接口的 .
GetScriptReferences()很简单, 返回路径为ExtExtenders.calendar.CalendarBehaviorExtender.js的ScriptReference对象实例.
GetScriptDescriptors()呢 ?
由代码可知.  作者先新建了一个ScriptControlDescriptor对象实例,
然后把ExtCalendar的各个对应Extjs的客户端Calendar组件的属性添加上述的descriptror中,在控件的Render()事件中利用控件所处页面的ScriptManager注册这个descriptor,达到与客户端元素交互的目的.

来到客户端的实现

CalendarExtenderBehavior.js


脚本代码的第2,3行分明声明了一个名为 ExtExtenders的命名空间以及该命名空间下的CalendarExtenderBehavior类. 在其后的原型声明中,initialize方法构造了一个客户端的Ext.form.DateField对象并且在页面呈现.
注意到js文件里有一系列get_XX, set_XX方法  它的作用就是按照get(set)_PropertyName的格式来传递服务器端ScriptDescriptor对象所具有的Property值.
最后一行, 作者把CalendarExtenderBehavior作为Sys.UI.Control的子类注册.

使用YuiGrid

首先下载一个ExtExtenders.dll的玩意,google上很多,就不具体说哪里下载了 /Files/guguangye/ExtExtenders.rar ,我也顺便提供一个我目前在用的版本。

    首先把这个DLL添加到工具箱。

   

上述这些就是基本ExtExtenders基本控件了。

每用到一个再对该控件做一个详细介绍,今天先用了YUIGrid。

在使用ExtExtenders之前,首先要在web.config上做配置,否则会出现 未将对象引用实例的 黄页,这个是必须的。

Code

 

OK,拖控件。在aspx文件中生成

Code

 

如果只是用来测试,不手动绑定数据,记得在<cc1:YuiGrid>中设置AutoGenerateColumns=true,默认是false,所以不会显示数据。

可以放置一个ScriptManagerUpdatePanel作用是添加数据时达到局部刷新的效果。

在上述页面中,我把YuiGrid和两个textbox以及提交按钮放置在一个UpdatePanel中。

dataIndex代表绑定列名  hidden代表是否隐藏。

最后记得绑定对象,当然可以是泛型集合,dataset等等。

Code

 

上面是整个效果图。

当然分页功能目前只是摆设,下次继续做分页功能和进一步对YuiGrid进行学习。

下面是生成的客户端代码,供参考

 

Code

 

posted on 2009-07-28 16:47  渔人码头  阅读(863)  评论(1编辑  收藏  举报

导航