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的接口,小菜還沒有完全弄明白它的原理。

希望,給位大牛給點意見!希望大家同路人多交流,道不同的就不相為謀好了!歡迎拍磚。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM