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测试过没有问题。

视图例子:

Asp.net WebForm DropDownList 无限极联动(不需要写C#代码,不需要写JS,只是配置属性)只是做了一个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的接口,小菜还没有完全弄明白它的原理。

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

你可能感兴趣的:(asp.net)