Asp.net WebForm DropDownList 无限极联动(不需要写C#代码,不需要写JS,只是配置属性)

1.承上启下

2.新增的功能

3.源码

4.小结

承上启下(一些废话,与今天同事的一点对话。小菜:26岁。 同事:30岁。)

上一篇 Asp.net Webform 数据源绑定控件的扩展(懒人的办法):DropDownList

中提到了根据界面属性来动态绑定 DropDownList ,并跟本公司的同事讨论了下,同事的意思是没有必要写控件,原因如下:1. 没有时间写。 2. 后台取读取数据挺方便的(通过硬编码的方式)。一下是小菜跟公司同事的一点点对话,原文如下:

小菜说:现在写了以后一劳永逸。(点评:小菜只是想把封装一下控件的好处阐明一下,希望同事们一起向这方面努力!公司有自己的易用快速开发框架!因为公司的开发环境现在是,硬编码满天飞,没有一个统一的标准!)

同事说:没必要写控件。(点评:小菜很迷惑为什么没有必要,小菜很困惑。)

小菜:为什么没必要,写好了控件。以后业务变更都不需要重新编译,现在每次都要在 Page_Load 里面加载数据,手写代码,如果一旦数据改变,使用 DropDownList 的源码都可能需要更改!

(点评:小菜提出自己的困惑,并通过阐明自己写扩展控件的原因)

同事:不是每次都在 Page_Load 里面加载的?(点评:我想我说的是扩展控件的利弊,不知道为什么同事会提出这个问题?以此做突破口,打败我?)

小菜:不再Page_Load里面加载你数据怎么来?(点评:小菜想了想,感觉无论什么框架,数据在DB也好在文件中也好,肯定得加载到控件端的!小菜接招了!)

同事:你做DropDownList联动的时候,一开始怎么会从DropDownList里面读取呢?(点评:提出假设,同事说的不错。不过小菜想说,我做控件的初衷就是屏蔽代码中的不可控性,提高代码扩展,修改的性能,这种的确是不再Page_Load中加载,但是... ... 大家都明白... ...这一局同事完胜我了,成功了抓住了我语句中的漏洞,我输了!)

小菜:这个我知道但是,这些也要写在cs文件里面啊,也要人为的去写逻辑啊!()(点评:提出者中做法也是有小菜初衷所要解决的问题。)

同事:没必要,你以为开发控件那么容易,根本没时间。(点评:另一个理由,貌似又要回到问题的原点。)

小菜: ... ...(点评:小菜认输了,沉默了... ...)

总结:一些题外话。小菜是个真心喜欢技术的人,对于时间问题小菜想说,每个人都是24个小时,为什么我有时间你没有呢?小菜每天都是1-2点睡觉,7点上班的,下班后回家吃饭,开电脑,然后就是博客园。写代码。睡觉,小菜的技术就这样不是什么高深的东西,也写不出大牛的水平(例如:@Fish Li,我很喜欢他。他的技术都是一针见血的。)但是小菜今年只有26岁,毕业两年,北京工作一年,小菜还很年轻,小菜会一直努力。至于现在我们公司的开发环境来说,我大三的水平时候就能胜任现在的开发任务(就当我是吹牛吧,别拍砖!)。小菜没有浑浑噩噩,也没有放弃对编程的追求。现实的因素左右过我,但是不能决定我。我会一直努力... ... 对于那些只把技术当做混饭吃的工具的人,我不能说你什么!每个人都有自己的选择和处事方法,我只是希望那些真正耐得住寂寞的喜欢编程的人,多交流,小菜向你们多学习。通过自己的志趣,跟自己的生活家庭带来更好的生活。技术,编程,学习不是生活,但也不能这么浑浑噩噩吧?

 

新增加的功能

对原有功能的扩展,增加了4个新的属性,以此来实现DropDownList的联动功能,支持无限极联动。使用IE 9,Chrome测试过没有问题。

视图例子:

只是做了一个4级联动小例子,不依赖数据库,只依赖我写的数据库操作类,你也可以把数据库操作类自己重写,来实现。

源代码

FindControl Extends
 1     public static Control FindAllControl(this System.Web.UI.Control control, string controlID)
 2         {
 3             return FindControlForeach(control, controlID);
 4         }
 5 
 6         private static Control FindControlForeach(Control control, string controlID)
 7         {
 8             Control findResult = control.FindControl(controlID);
 9             if (findResult == null)
10             {
11                 foreach (Control childControl in control.Controls)
12                 {
13                     findResult = FindControlForeach(childControl, controlID);
14                     if (findResult != null) break;
15                 }
16             }
17             return findResult;
18         }

由于新增了联动功能,所以需要后台自动识别联动控件的ID所以扩展了 Control 的FindControl 功能。

一下是Page.aspx需要的属性设计(刚才吃着吃着饭,想起来没加!汗!)

Aspx Code
 1 <div>
 2     
 3         <bsp:DropDownList ID="DropDownList1" runat="server" ConnectionName="Platform" 
 4             DataTextField="ObjectName" DataValueField="PKey" DefaultText="-全部-" 
 5             RelevanceID="DropDownList2" SortName="ObjectOrderBy" TableName="RBAC_View" 
 6             Where="ParentKey is null">
 7         </bsp:DropDownList>
 8         <bsp:DropDownList ID="DropDownList2" runat="server" ConnectionName="Platform" 
 9             DataTextField="ObjectName" DataValueField="UserPKey" DefaultText="-全部-" 
10             RelevanceID="DropDownList3" RelevanceName="ParentKey" SortName="ObjectOrderBy" 
11             TableName="RBAC_View" Where="PKey=null">
12         </bsp:DropDownList>
13         <bsp:DropDownList ID="DropDownList3" runat="server" ConnectionName="Platform" 
14             DataTextField="UserName" DataValueField="PKey" DefaultText="-请选择-" 
15             RelevanceName="PKey" TableName="RBAC_Users" Where="Pkey is null" 
16             RelevanceID="DropDownList4">
17         </bsp:DropDownList>
18         <bsp:DropDownList ID="DropDownList4" runat="server" ConnectionName="Platform" 
19             DataTextField="ObjectName" DataValueField="PKey" DefaultText="-请选择-" 
20             RelevanceName="UserPkey" SortName="ObjectOrderBy" TableName="RBAC_View" 
21             Where="1=2">
22         </bsp:DropDownList>
23     
24     </div>
DropDownList
  1     [DefaultProperty("Text")]
  2     [ToolboxData("<{0}:DropDownList runat=server></{0}:DropDownList>")]
  3     public class DropDownList : System.Web.UI.WebControls.DropDownList
  4     {
  5         #region Extends Attributes
  6 
  7         private Database DataAccess;
  8 
  9         /// <summary>
 10         /// 摘要: 操作数据库的 TableName
 11         /// </summary>
 12         [Bindable(true)]
 13         [Category("Extends")]
 14         [DefaultValue("")]
 15         [Localizable(true)]
 16         public string TableName
 17         {
 18             get
 19             {
 20                 String s = (String)ViewState["TableName"];
 21                 return ((s == null) ? String.Empty : s);
 22             }
 23 
 24             set
 25             {
 26                 ViewState["TableName"] = value;
 27             }
 28         }
 29         /// <summary>
 30         /// 摘要: 操作数据库的 ConnectionName
 31         /// </summary>
 32         [Bindable(true)]
 33         [Category("Extends")]
 34         [DefaultValue("")]
 35         [Localizable(true)]
 36         public string ConnectionName
 37         {
 38             get
 39             {
 40                 String s = (String)ViewState["ConnectionName"];
 41                 return ((s == null) ? String.Empty : s);
 42             }
 43 
 44             set
 45             {
 46                 ViewState["ConnectionName"] = value;
 47             }
 48         }
 49         /// <summary>
 50         /// 摘要: DropDownList 默认选项,空则为默认选项
 51         /// </summary>
 52         [Bindable(true)]
 53         [Category("Extends")]
 54         [DefaultValue("")]
 55         [Localizable(true)]
 56         public string DefaultText
 57         {
 58             get
 59             {
 60                 String s = (String)ViewState["DefaultText"];
 61                 return ((s == null) ? String.Empty : s);
 62             }
 63 
 64             set
 65             {
 66                 ViewState["DefaultText"] = value;
 67             }
 68         }
 69         /// <summary>
 70         /// 摘要: 操作数据库的表的 WHERE 条件
 71         /// </summary>
 72         [Bindable(true)]
 73         [Category("Extends")]
 74         [DefaultValue("")]
 75         [Localizable(true)]
 76         public string Where
 77         {
 78             get
 79             {
 80                 String s = (String)ViewState["Where"];
 81                 return ((s == null) ? "1=1" : s);
 82             }
 83 
 84             set
 85             {
 86                 ViewState["Where"] = value;
 87             }
 88         }
 89         /// <summary>
 90         /// 摘要: 排序字段,空则为 DataTextField
 91         /// </summary>
 92         [Bindable(true)]
 93         [Category("Extends")]
 94         [DefaultValue("")]
 95         [Localizable(true)]
 96         public string SortName
 97         {
 98             get
 99             {
100                 String s = (String)ViewState["SortName"];
101                 return ((s == null) ? this.DataTextField : s);
102             }
103 
104             set
105             {
106                 ViewState["SortName"] = value;
107             }
108         }
109         /// <summary>
110         /// 摘要: 以此 DataValueFiled 为主的联动 DropDownList.ID
111         /// </summary>
112         [Bindable(true)]
113         [Category("Extends")]
114         [DefaultValue("")]
115         [Localizable(true)]
116         public string RelevanceID
117         {
118             get
119             {
120                 String s = (String)ViewState["RelevanceID"];
121                 return ((s == null) ? string.Empty : s);
122             }
123             set
124             {
125                 ViewState["RelevanceID"] = value; if (!string.IsNullOrEmpty(value)) { this.AutoPostBack = true; }
126             }
127         }
128         /// <summary>
129         /// 摘要: 接收父级 DropDownList 的值的对应字段
130         /// </summary>
131         [Bindable(true)]
132         [Category("Extends")]
133         [DefaultValue("")]
134         [Localizable(true)]
135         public string RelevanceName
136         {
137             get
138             {
139                 String s = (String)ViewState["RelevanceName"];
140                 return ((s == null) ? string.Empty : s);
141             }
142             set
143             {
144                 ViewState["RelevanceName"] = value;
145             }
146         }
147         /// <summary>
148         /// 摘要: 是否联动父集
149         /// </summary>
150         [Bindable(true)]
151         [Category("Extends")]
152         [DefaultValue("")]
153         [Localizable(true)]
154         public bool IsRelevanceChild
155         {
156             get
157             {
158                 String s = (String)ViewState["RelevanceName"];
159                 return !(s == null);
160             }
161         }
162         /// <summary>
163         /// 摘要: 是否联动子集
164         /// </summary>
165         [Bindable(true)]
166         [Category("Extends")]
167         [DefaultValue("")]
168         [Localizable(true)]
169         public bool IsRelevanceFather
170         {
171             get
172             {
173                 String s = (String)ViewState["RelevanceID"];
174                 return !(s == null);
175             }
176         }
177 
178         #endregion
179 
180         #region Override Method
181 
182         protected override void OnDataBinding(EventArgs e)
183         {
184             LoadData();
185             base.OnDataBinding(e);
186         }
187 
188         protected override void OnDataBound(EventArgs e)
189         {
190             base.OnDataBound(e);
191             InsertDefaultText();
192             RelevanceOther();
193            
194         }
195 
196         protected override void OnPagePreLoad(object sender, EventArgs e)
197         {
198             if (!Page.IsPostBack)
199                 this.DataBind();
200             base.OnPagePreLoad(sender, e);
201         }
202 
203         protected override void OnSelectedIndexChanged(EventArgs e)
204         {
205             RelevanceOther();
206             base.OnSelectedIndexChanged(e);
207         }
208 
209         #endregion
210 
211         #region Private Method
212 
213         private void LoadData()
214         {
215             if (!string.IsNullOrEmpty(DataTextField) && !string.IsNullOrEmpty(DataTextField) && !string.IsNullOrEmpty(TableName))
216             {
217                 DataAccess = string.IsNullOrEmpty(ConnectionName) ?
218                     (this.Page as Binarysoft.Library.Web.UI.Page).DataAccess :
219                     DatabaseFactory.CreateDatabase(ConnectionName);
220                 this.DataSource = DataAccess.ExecuteDataTable(string.Format("SELECT {0},{1} FROM {2} WHERE {3} ORDER BY {4}", DataTextField, DataValueField, TableName, Where, SortName));
221             }
222         }
223 
224         private void InsertDefaultText()
225         {
226             if (!string.IsNullOrEmpty(DefaultText))
227                 this.Items.Insert(0, new ListItem(DefaultText, string.Empty));
228         }
229 
230         private void RelevanceOther()
231         {          
232             if (IsRelevanceFather)
233             {
234                 DropDownList findedControl = (this.Page.Form.FindAllControl(RelevanceID) as DropDownList);
235                 if (findedControl != null)
236                 {
237                     findedControl.Where = string.Format("{0} = '{1}'", findedControl.RelevanceName, this.SelectedValue);
238                     findedControl.DataBind();
239                 }
240             }
241         }
242 
243         #endregion
244     }

 

小结

这个控件,没有支持Ajax是我唯一感觉不足的地方。原因是,小菜还没最终决定,如何实现Ajax的功能,以下是小菜的一点想法,实现ajax功能:

1.使用Jquery,但是感觉前台一堆代码要手动维护。

2.使用系统自带的接口,代码有些冗余。

3.使用Anthem的接口,小菜还没有完全弄明白它的原理。

希望,给位大牛给点意见!希望大家同路人多交流,道不同的就不相为谋好了!欢迎拍砖。

posted @ 2013-03-17 20:10  E=mc&#178;  阅读(3531)  评论(9编辑  收藏  举报