探讨C#.NET下DropDownList的一个有趣的bug及其解决办法
2010-02-03 13:44
344 查看
摘要:
本文就C#.Net环境下Web开发中经常使用的DropDownList控件的SelectedIndex属性进行了详细的探讨,发现了这一属性在使用中存在的问题,并经过测试,提出了回避和解决的办法。
关键词:
DropDownList,SelectedIndex,跟踪调试,C#.NET
ProbeIntoABugofDropDownListinC#.NETandtheResolvent
Abstract:
Thisarticlehavediscussedtheattribute-SelectedIndexofDropDownListControl,whichisfrequentlyusedinthedevelopmentenvironmentofC#.Net.Bytracingtheprogramindetail,findoutthereasonofthisbug.Giveouttheschemeofhowtoavoidofandresolventit.
Keywords:
DropDownList,SelectedIndex,Debug,Traceinto,C#.NET
1.引言
信息和网络的发展,使基于Web应用的系统越来越普及,VS.Net无疑是开发Web应用的系统的最合适的工具之一。但我们在长期的开发实践中发现,C#.Net下DropDownList控件在使用过程中会遇到一些问题,它的SelectedIndex属性存在一个读写缺陷,这个问题也一直困扰着其他的开发人员。因此,本文专门对DropDownList做了详细的测试,来探求问题所在和解决办法。
2.DropDownList控件介绍
DropDownList是C#.Net控件面板WebForm下的一个控件,它的命名空间是System.Web.UI.WebControls.DropDownList。它是一个允许用户从下拉列表中选择一项的控件,通过在DropDownList控件的开始和结束标记之间为每个项放置一个ListItem对象,可以指定希望显示在DropDownList控件中的项,也支持数据绑定。DropDownList的功能决定了它在日常开发中的实用性,在数据输入控件中其使用率仅次于TextBox。通过预先设定或动态数据绑定将其填入可供用户选择的数据,既方便了用户操作,增强软件的易用性,又能有效的规范数据输入,成为软件开发人员最常选择的控件之一。
3.关于SelectedIndex的有趣的问题
在长期的使用过程中我们发现,当在程序中动态将DropDownList列表中的某项选定,
或指定SelectedIndex为某一值时,会出现意想不到的错误。而使用断点跟踪调试方法或将SelectedIndex值读取到某个变量进行测试,却难以找到问题所在。
3.1发现问题
假设有如下简单代码
privatevoidPage_Load(objectsender,System.EventArgse)
{if(!IsPostBack)
{//初始化DropDownList下拉列表
Init_FillList();
}
}
privatevoidbtnOK_Click(objectsender,System.EventArgse)
{stringstrID=txtContinentID.Text.Trim();
//选择指定项
listContinent.Items.FindByValue(strID).Selected=true;
Response.Write("OK!");
}
#region初始化下拉列表方法
privatevoidInit_FillList()
{//定义ListItem对象
ListItemitem;
//清空列表
listContinent.Items.Clear();
//写入列表
listContinent.Items.Add("");
item=newListItem("亚洲","Asia");
listContinent.Items.Add(item);
item=newListItem("欧洲","Euro");
listContinent.Items.Add(item);
item=newListItem("美洲","Amer");
listContinent.Items.Add(item);
}
#endregion
把它放到一个简单web页面中直接运行,在输入框中输入大洲编号Asia,Euro,Amer中的任一个,点击btnOK按钮键,看似没有任何问题的代码,报出了如下VS.Net著名的错误黄页:(记为:错误A)
DropDownList不能有多个项被选定。
说明:执行当前Web请求期间,出现未处理的异常。请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息。异常详细信息:System.Web.HttpException:DropDownList不能有多个项被选定。
[/code]
[/code]
[/code]
privatevoidPage_Load(objectsender,System.EventArgse)
{//去掉if(!IsPostBack)每次都重写数据
Init_FillList();
[/code]
[/code]
privatevoidtxtOK2_Click(objectsender,System.EventArgse)
{stringstrID=txtContinentID.Text.Trim();
this.listContinent.SelectedIndex=-1;//新加行
listContinent.Items.FindByValue(strID).Selected=true;
Response.Write("OK!");
[/code]
[/code]
[/code]
privatevoidbtnOK3_Click(objectsender,System.EventArgse)
{//新加行调试后知i=0
inti=listContinent.SelectedIndex;
stringstrID=txtContinentID.Text.Trim();
this.listContinent.SelectedIndex=-1;
//新加行调试后知j=0
intj=this.listContinent.SelectedIndex;
listContinent.Items.FindByValue(strID).Selected=true;
Response.Write("OK!");
}
运行程序,真正的问题出现了,不管在debug状态还是非调试状态,都是一样的“DropDownList不能有多个项被选定”错误。这说明SelectedIndex的值根本不能进行查看或读取,这也进一步证明C#.Net中对SelectedIndex的读取实现代码有问题,存在不安全的判断。
另外,经过此时的调试观察i和j的返回值是一样的结果,这个结果也和系统规定的SelectedIndex的默认值为0一致。这证明了this.listContinent.SelectedIndex=-1这行代码在txtOK2_Click()中是没有起作用没有用途的,然而加上该行代码却能解决问题,使程序正常运行。
3.5问题根源
通过反编译工具和.NET源码的帮助,找到了C#.Net中关于DropDownList的源码实现,发现了这个问题存在的根源。以下是C#.Net中DropDownList的SelectedIndex属性源码实现:
[/code]
}
这段源码实现表明,在取SelectedIndex时自动进行了判断,只要有数据那么Selected的值就肯定大于等于0,所以我们在查看时发现设置成-1是无效的,它会自动改为0。另外它还做了另外一部操作this.Items[0].Selected=true,这个也就是直接导致Exception产生的原因(开发者只是想看看SelectedIndex它就把Item[0]的Selected值给改了…),所以在调试程序时要注意回避这个问题,我们只能通过修改代码使程序运行正常,而无法改变VS.NET的源码实现。
图一是程序测试界面,btnOK,btnOK2,btnOK3和列表数据绑定代码的实现已在上面给出。
4.结束语
经调试,在初始设置SelectedIndex=0的情况下同样存在“错误A”的问题。而且若将3.3中SelectedIndex=-1改为SelectedIndex=0,此中情况程序不调试运行也会出现“错误A”。
在系统对效率要求不高,数据量小的情况下可以采用3.2的方法来回避这个问题,即每次加载页面重新初始化DropDownList列表。也可采取3.3中将SelectedIndex设为-1的方法来改进这一问题,但此时不要对SelectedIndex=-1行进行单行调试。两种方法在工程交付运行时都不会有任何因为SelectedIndex而引起的程序错误。
该文所有测试在Microsoft.NETFramework1.1,C#.NET2003version7.1,IE6.0环境下编写调试。
参考资料
[1].[美]G.AndrewDuthie著,《ASP.NET程序设计》[M],清华大学出版社,2002.7
[2].林煌章,《ASP.NET程式设计》[M],清华大学出版社,2001.6
[3].MicrosoftCoporation:http://www.microsoft.com/msdn
本文就C#.Net环境下Web开发中经常使用的DropDownList控件的SelectedIndex属性进行了详细的探讨,发现了这一属性在使用中存在的问题,并经过测试,提出了回避和解决的办法。
关键词:
DropDownList,SelectedIndex,跟踪调试,C#.NET
ProbeIntoABugofDropDownListinC#.NETandtheResolvent
Abstract:
Thisarticlehavediscussedtheattribute-SelectedIndexofDropDownListControl,whichisfrequentlyusedinthedevelopmentenvironmentofC#.Net.Bytracingtheprogramindetail,findoutthereasonofthisbug.Giveouttheschemeofhowtoavoidofandresolventit.
Keywords:
DropDownList,SelectedIndex,Debug,Traceinto,C#.NET
1.引言
信息和网络的发展,使基于Web应用的系统越来越普及,VS.Net无疑是开发Web应用的系统的最合适的工具之一。但我们在长期的开发实践中发现,C#.Net下DropDownList控件在使用过程中会遇到一些问题,它的SelectedIndex属性存在一个读写缺陷,这个问题也一直困扰着其他的开发人员。因此,本文专门对DropDownList做了详细的测试,来探求问题所在和解决办法。
2.DropDownList控件介绍
DropDownList是C#.Net控件面板WebForm下的一个控件,它的命名空间是System.Web.UI.WebControls.DropDownList。它是一个允许用户从下拉列表中选择一项的控件,通过在DropDownList控件的开始和结束标记之间为每个项放置一个ListItem对象,可以指定希望显示在DropDownList控件中的项,也支持数据绑定。DropDownList的功能决定了它在日常开发中的实用性,在数据输入控件中其使用率仅次于TextBox。通过预先设定或动态数据绑定将其填入可供用户选择的数据,既方便了用户操作,增强软件的易用性,又能有效的规范数据输入,成为软件开发人员最常选择的控件之一。
3.关于SelectedIndex的有趣的问题
在长期的使用过程中我们发现,当在程序中动态将DropDownList列表中的某项选定,
或指定SelectedIndex为某一值时,会出现意想不到的错误。而使用断点跟踪调试方法或将SelectedIndex值读取到某个变量进行测试,却难以找到问题所在。
3.1发现问题
假设有如下简单代码
privatevoidPage_Load(objectsender,System.EventArgse)
{if(!IsPostBack)
{//初始化DropDownList下拉列表
Init_FillList();
}
}
privatevoidbtnOK_Click(objectsender,System.EventArgse)
{stringstrID=txtContinentID.Text.Trim();
//选择指定项
listContinent.Items.FindByValue(strID).Selected=true;
Response.Write("OK!");
}
#region初始化下拉列表方法
privatevoidInit_FillList()
{//定义ListItem对象
ListItemitem;
//清空列表
listContinent.Items.Clear();
//写入列表
listContinent.Items.Add("");
item=newListItem("亚洲","Asia");
listContinent.Items.Add(item);
item=newListItem("欧洲","Euro");
listContinent.Items.Add(item);
item=newListItem("美洲","Amer");
listContinent.Items.Add(item);
}
#endregion
把它放到一个简单web页面中直接运行,在输入框中输入大洲编号Asia,Euro,Amer中的任一个,点击btnOK按钮键,看似没有任何问题的代码,报出了如下VS.Net著名的错误黄页:(记为:错误A)
DropDownList不能有多个项被选定。
说明:执行当前Web请求期间,出现未处理的异常。请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息。异常详细信息:System.Web.HttpException:DropDownList不能有多个项被选定。
通过认真核查代码并查询联机帮助,发现DropDownList的使用符合相关
说明文档的使用方法,没有任何问题。 [code]
[/code]
为了跟踪查找错误的原因,在btnOK_Click()事件下的所有代码外围加
try…catch保护进行调试,单步执行,发现一直执行
到Response.Write("OK!")句,程序都没有跳出,继续向下,此时该事件已经
执行完了,没有错误,应该显示出正常的web页面,就在这时,上面的错误
黄页又出现了。调试无法找到错误所在,如何才能解决这个问题,
难道是开发工具的原因,于是想到以下办法.
[code]
[/code]
3.2问题暂时解决
不能有多个项被选定,可能是因为DropDownList在选择新项之前不能自动去除原来
的选择,即,不能有效的对已添入数据的列表进行初始化。于是在每次PostBack后
将DropDownList的数据重新绑定刷新恢复到系统自己规定的默认值,然后再
进行新的项的选择,将Page_Load()事件下的代码做如下调整
[code]
[/code]
privatevoidPage_Load(objectsender,System.EventArgse)
{//去掉if(!IsPostBack)每次都重写数据
Init_FillList();
}
此时再运行程序,不再出现错误A,运行正常。
但是web应用不同于局域网内系统的应用,它对程序执行效率要求更高,
要尽量减少对服务器的访问。如果一个页面在每次刷新时都要重新
访问服务器初始化数据地话,会严重增加服务器的负担。一旦数据量大
或访问的终端增多,将会使页面显示变的非常慢,客户无法忍受。
需要继续寻求其他的解决办法。
[code]
[/code]
3.3有趣的bug
由于过去曾经长期从事Delphi下的应用系统的开发,对Combox控件的
使用非常熟悉,由于他们的功能基本相同,推断其使用方法应该也是
有些相通的,于是对txtOK_Click()进行修改,得txtOK2_Click()事件:
[code]
[/code]
privatevoidtxtOK2_Click(objectsender,System.EventArgse)
{stringstrID=txtContinentID.Text.Trim();
this.listContinent.SelectedIndex=-1;//新加行
listContinent.Items.FindByValue(strID).Selected=true;
Response.Write("OK!");
}
运行程序,果然在加上IsPostBack判断的情况下,程序仍能正常运行。
然而这与msdn联机帮助对DropDownList的使用说明是不符的。
相关的属性说明:“DropDownList.SelectedIndex属性,
DropDownList控件中的选定项的索引。默认值为0,该值选择列表中的
第一项。备注使用SelectedIndex属性以编程方式指定或确定
DropDownList控件中的选定项的索引。DropDownList控件中总是选择一项。
无法在列表中同时取消选择所有项。注意DropDownList控件中的项的
索引从零开始”。有趣的是不符合使用规定的程序没有报任何错误,
反而使程序运行正常。
[code]
[/code]
为了查看SelectedIndex在运行时的实际值是0还是1或其他的值,再次跟踪
调试,此时发现了一个有趣的bug。把断点设置到
this.listContinent.SelectedIndex=-1行,当程序运行到这里时将鼠标移到
SelectedIndex的位置,查看它的值,(或者通过开发环境下边的变量
查看器查看),发现此时的值是0,继续向下运行,错误A又出现了。
而同样是调试状态,单步执行代码,只是不进行查看SelectedIndex的操作
(通过变量查看器看也不可以),直到跟踪完毕,程序运行也没有问题。
很明显,这是C#.Net的一个bug。
[code]
[/code]
3.4换一种取值方式
既然不能在调试时通过系统的返回值提示查看变量值,只能变通一下,
通过自己定义变量来获取SelectedIndex的值。于是对txtOK2_Click()
进行修改,得txtOK3_Click()事件:
[code]
[/code]
privatevoidbtnOK3_Click(objectsender,System.EventArgse)
{//新加行调试后知i=0
inti=listContinent.SelectedIndex;
stringstrID=txtContinentID.Text.Trim();
this.listContinent.SelectedIndex=-1;
//新加行调试后知j=0
intj=this.listContinent.SelectedIndex;
listContinent.Items.FindByValue(strID).Selected=true;
Response.Write("OK!");
}
运行程序,真正的问题出现了,不管在debug状态还是非调试状态,都是一样的“DropDownList不能有多个项被选定”错误。这说明SelectedIndex的值根本不能进行查看或读取,这也进一步证明C#.Net中对SelectedIndex的读取实现代码有问题,存在不安全的判断。
另外,经过此时的调试观察i和j的返回值是一样的结果,这个结果也和系统规定的SelectedIndex的默认值为0一致。这证明了this.listContinent.SelectedIndex=-1这行代码在txtOK2_Click()中是没有起作用没有用途的,然而加上该行代码却能解决问题,使程序正常运行。
3.5问题根源
通过反编译工具和.NET源码的帮助,找到了C#.Net中关于DropDownList的源码实现,发现了这个问题存在的根源。以下是C#.Net中DropDownList的SelectedIndex属性源码实现:
[WebCategory("Behavior"), DesignerSerializationVisibility(
DesignerSerializationVisibility. Hidden), DefaultValue(0), WebSysDescription(
"DropDownList_SelectedIndex")]
[code]
[/code]
publicoverrideintSelectedIndex
{
get
{
intnum1=base. SelectedIndex;
if((num1<0)&&(this.Items. Count>0))
{
this.Items[0]. Selected=true;
num1=0;
}
returnnum1;
}
set
{
base.SelectedIndex=value;
}
}
这段源码实现表明,在取SelectedIndex时自动进行了判断,只要有数据那么Selected的值就肯定大于等于0,所以我们在查看时发现设置成-1是无效的,它会自动改为0。另外它还做了另外一部操作this.Items[0].Selected=true,这个也就是直接导致Exception产生的原因(开发者只是想看看SelectedIndex它就把Item[0]的Selected值给改了…),所以在调试程序时要注意回避这个问题,我们只能通过修改代码使程序运行正常,而无法改变VS.NET的源码实现。
图一是程序测试界面,btnOK,btnOK2,btnOK3和列表数据绑定代码的实现已在上面给出。
4.结束语
经调试,在初始设置SelectedIndex=0的情况下同样存在“错误A”的问题。而且若将3.3中SelectedIndex=-1改为SelectedIndex=0,此中情况程序不调试运行也会出现“错误A”。
在系统对效率要求不高,数据量小的情况下可以采用3.2的方法来回避这个问题,即每次加载页面重新初始化DropDownList列表。也可采取3.3中将SelectedIndex设为-1的方法来改进这一问题,但此时不要对SelectedIndex=-1行进行单行调试。两种方法在工程交付运行时都不会有任何因为SelectedIndex而引起的程序错误。
该文所有测试在Microsoft.NETFramework1.1,C#.NET2003version7.1,IE6.0环境下编写调试。
参考资料
[1].[美]G.AndrewDuthie著,《ASP.NET程序设计》[M],清华大学出版社,2002.7
[2].林煌章,《ASP.NET程式设计》[M],清华大学出版社,2001.6
[3].MicrosoftCoporation:
相关文章推荐
- 探讨C#.NET下DropDownList的一个有趣的bug及其解决办法
- c#.net无法直接启动带有“类库输出类型”的项目 若要调试此项目,请在此解决方案中添加一个引用库项目的可执行项目。将这个可执行项目设置为启动项-----解决办法
- VS2013自定义向导工程的一个bug及其解决办法
- 常量,字段,构造方法 调试 ms 源代码 一个C#二维码图片识别的Demo 近期ASP.NET问题汇总及对应的解决办法 c# chart控件柱状图,改变柱子宽度 使用C#创建Windows服务 C#服务端判断客户端socket是否已断开的方法 线程 线程池 Task .NET 单元测试的利剑——模拟框架Moq
- PopWindow在Android 2.3.3 或以下的系统的一个bug 及其解决办法
- C#技巧【调用线程无法访问此对象,因为另一个线程拥有该对象的问题的解决办法】【C#读写EXCEL源码提示“office检测到此文件存在一个问题。为帮助保护您的计算机,不能打开此文件”的解决】
- C# asp.net页面通过URL参数传值中文乱码问题解决办法
- 2005ReportingServices的一个bug及其解决方法
- IE6绝对定位的bug及其解决办法
- C#解决“Emgu.CV.CvInvoke”的类型初始值设定项引发异常 的其中一个办法
- phpexcel移植到sae上的一个致命bug的解决的办法
- C# post数据时 出现如下错误: System.Net.WebException: 远程服务器返回错误: (417) Expectation Failed 的解决办法
- ASP.NET时代的安全性漏洞及其解决办法
- Silverlight:telerik RadControls中RadGridView的一个Bug及解决办法(转载)
- 关于一个给二维数组循环赋值问题的本渣研究出的解决办法[C#]
- c# winform 在一个窗体中使用另一个窗体中TextBox控件的值——解决办法
- 关于DropDownList的一个有趣的Bug~
- 关于“DropDownList 有一个无效 SelectedValue,原因是它不存在于项目列表中”的解决办法
- 在C#编程中要将一个表中的数据复制到另一个表中出现报错“该行已经属于另一个表”解决办法
- 一个非常简单的Oracle存储过程,及其在C#.net中的执行的代码