原创ComboBox详解—SelectedIndexChanged与属性值变化

标签:
控件行处属性数据源nullit |
分类: .Net |
ComboBox控件(以下简称cb)在.net编程中很常用,下面把我个人使用这个空间时遇到的问题和学到的东西总结一下,供大家分享。
1.先说一下我对这个控件的习惯用法
DataSource绑定时,绑定一个dataTable(从数据库中取出来的);
用户交互时的事件调用,用SelectedIndexChanged()方法;
本文就以上面的用法为例,着重说一下SelectedIndexChanged()方法的执行过程和其间cb各属性值的变化过程。这些属性值(主要是他们的变化过程)如果没有弄的很清楚的话,在用的过程中很可能会出现想不到的错误,比如碰到null。主要是以下四个属性:
SelectedIndex
SelectedText
Text
SelectedValue.ToString()
2.SelectedIndexChanged()方法的执行
SelectedIndexChanged()方法在cb的DataSource发生改变时就会被调用,而不是用户在选一下时才会被调用。而且在cb的displaymember属性被赋值时,SelectedIndexChanged()方法也会被调用!
通常,如果用户交互(把cb拉下来选了某一项)之后,再在程序中读cb的属性是不会出问题的,因为用户交互之后,属性值就很明确了。问题就出在用户没有交互时,用到上面提到的属性值。这种情况是有的,因为cb显示出来后,默认显示DataSource里的第一项的值,而用户刚好就想用第一个值,那么他就不用再拉下来选一下了。
下面以我的代码为例,讲一下SelectedIndexChanged()方法是如何执行的。
代码如下:
其中数据源dt的内容如下:
我在316行处(也就是绑定cb的数据源时)打了一个断点,然后单步跟踪,执行过程如下:
(1)执行316行,绑定数据源;
(2)进入到SelectedIndexChanged()方法执行,而不是执行317行;
(3)SelectedIndexChanged()方法执行结束后,返回到316行处(但316行不会再执行了);
(4)执行317行,设定displaymember属性;
(5)进入到SelectedIndexChanged()方法执行;
(6)返回到317行,执行318行;
(7)执行319行,直到bindPayType()方法执行结束。
也就是说,绑定datasource和设定displaymember属性会触发cb的SelectedIndexChanged事件。而设定valuemember和tag的值则不会触发。
另外,如果设定displaymember属性在绑定datasource之前执行(316和317行互换一下),则设定displaymember属性不会触发SelectedIndexChanged事件。只有绑定datasource之后再设定displaymember才会触发SelectedIndexChanged事件。而且先设定displaymember与后设定,cb的Text的值(第二段代码输出测试)也不一样。先设定的话,执行SelectedIndexChanged()方法(注意只执行一次)时,cb的Text的值为"现金",就是dt的第一行对应元素的值;而后设定的话,第一次执行SelectedIndexChanged()方法,cb的Text的值是System.Data.DataRowView,第二次执行时才是"现金"。也就是说,在设定了displaymember后,cb的Text的值才会是Datasource里第一行对应元素的值。(这很合理,就该是这样)
3.不同阶段cb的各属性的值
以所贴代码为例(设定displaymember在绑定datasource之后),结果如下:
|
第一次执行 selectedIndexChanged |
第二次执行 |
两次执行后(程序某处用到) |
用户交互(选了cb的第二个) |
SeletedIndex |
0 |
0 |
0 |
1 |
SelectedText |
Null |
Null |
Null |
Null |
Text |
System.Data. DataRowView |
"现金" |
"现金" |
"代金券" |
SelectedValue .ToString() |
同上 |
同左 |
"1" |
"2" |
可以看出SeletedIndex属性没用,尽量不要用。
4.一个问题
如果我定义一个变量schePayType(类成员变量),然后在SelectedIndexChanged()方法里执行
schePayType=cb.Text,而不是Console.out.writeLine(),也就是第二段代码如下:
那么,即便设定displaymember在绑定datasource之后,还是会只执行一遍SelectedIndexChanged()方法。
搞不懂为什么,难道是对外部变量进行赋值的原因?
5.应当注意的问题
如果想用户改选cb,就自动刷新某些数据,而程序中又用到SelectedIndexChanged()方法时,要注意SelectedIndexChanged()方法在用户还没交互时就很有可能被执行了(绑定datasource)。而这时如果读取cb的某些属性(作为查询数据库的条件),就有可能不是你认为的数据(有可能空,或者是System.Data.DataRowView)。
如果用上面提到的4个(其实是3个)属性做查询条件,那么
(1)查询前做一下判断(当然这个判断也有点麻烦);
(2)或者不采用用户改选cb就自动去查询的方法,而是让他再点个按钮再执行查询数据库。
(3)还有一种办法就是用SelectionChangeCommitted
在我的另一篇文章里也有提到ComboBox:
http://blog.sina.com.cn/s/blog_5efa55090100djbq.html
今天在这里做个全面的总结。