解决DropDownList常见问题三则

1,给SelectedValue赋值时,如果Items中没有该项,则报XXX异常; 2,在绑定时,如果数据源返回null,它将不做任何动作,而我们一般习惯清空; 3,在绑定到数据源,而数据源参数依赖于别的控件时,会触发两次数据源绑定。

我的解决方法就是重载DropDownList(比较菜),下面详细说说这三个小问题:

1,比如某个商品属于某个分类,然后分类被删除了,而商品表中记录的还是原来类别的ID,在绑定DropDownList时,就会报那个常见的异常。这个比较头疼,因为没有太好的办法使用代码控制。我们可以通过重载SelectedValue属性和PerformDataBinding方法来解决:

代码

 private const String ExceptionString = "(异常)";

 private String cachedSelectedValue;
 /// <summary>
 /// 已重载。加上未添加到列表的项。
 /// </summary>
 public override string SelectedValue
        {
 get
            {
 return base.SelectedValue;
            }
 set
            {
 if (Items.FindByValue(value) == null)
                {
 // 列表项中并没有该选项,自动加入,并打上异常标识
                    Items.Add(new ListItem(value + ExceptionString, value));
                    cachedSelectedValue = value;
                }
 base.SelectedValue = value;
            }
        }

 /// <summary>
 /// 绑定数据
 /// </summary>
 /// <param name="dataSource"></param>
 protected override void PerformDataBinding(IEnumerable dataSource)
        {
 base.PerformDataBinding(dataSource);

 if (cachedSelectedValue != null)
            {
                ClearSelection();

 // 重新设置选中项
                ListItem item = Items.FindByValue(cachedSelectedValue);
 if (item == null)
                {
                    item = new ListItem(cachedSelectedValue + ExceptionString, cachedSelectedValue);
                    Items.Add(item);
                }
                item.Selected = true;
            }
        }

2,在省市两级下拉联动的时候,如果第一级选择直辖市,没有下一级城市,第二个下拉就应该显示没有子城市或者就显示直辖市,或者干脆清空。而默认情况下,DropDownList是不做任何事情的。这个可以重载PerformSelect实现(含第三点的实现代码):

代码

 private Boolean selecting =false;
///<summary>
/// 已重载。避免绑定时重入该方法
///</summary>
protectedoverridevoid PerformSelect()
        {
if (selecting) return;
            selecting =true;
if (!this.AppendDataBoundItems)
            {
// DropDownList在绑定时,如果数据源返回null,它将不做任何动作,而我们一般习惯清空
this.Items.Clear();
            }
base.PerformSelect();
            selecting =false;
        }

3, 仍然是省市两级下拉联动的例子,这两个DropDownList分别绑定两个ObjectDataSource,对应实体类的Area.FindAllByParentID(Int32 parentID)。第一个下来可以设定参数为固定值0,表示顶级地区

<asp:Parameter DefaultValue="0" Name="parentID" Type="Int32"/>

;第二个下拉可以使用ControlParameter,依赖于第一个下拉的选择

<asp:ControlParameter ControlID="DropDownList1" Name="parentID" PropertyName="SelectedValue" Type="Int32" />

这个时候,如果在FindAllByParentID下断点,会发现第二个下拉触发了两次绑定

经过一番探索发现:首先是第二个DropDownList的DataBind,触发了ObjectDataSource的Select,而在准备Select的参数的时候,需要调用参数的UpdateValue去取依赖控件的值,正是这个UpdateValue,触发了DataSourceChanged(实际比较复杂,这里为了易懂,从简),然后再次Select……

看看基类 DataBoundControlPerformSelect方法

代码

protectedoverridevoid PerformSelect()
{
if (this.DataSourceID.Length ==0)
    {
this.OnDataBinding(EventArgs.Empty);
    }
    DataSourceView data =this.GetData();
this._arguments =this.CreateDataSourceSelectArguments();
this._ignoreDataSourceViewChanged =true;
base.RequiresDataBinding =false;
this.MarkAsDataBound();
    data.Select(this._arguments, new DataSourceViewSelectCallback(this.OnDataSourceViewSelectCallback));
}

很明显,_ignoreDataSourceViewChanged字段就是专门解决这个问题的。也就是说,控件团队已经意识到会存在这种问题,所以在这里留了一手。但是为什么这一手没有生效呢? 我们来看看DropDownList的父类 ListControl,杯具,它重载了PerformSelect

protectedoverridevoid PerformSelect()
{
this.OnDataBinding(EventArgs.Empty);
base.RequiresDataBinding =false;
base.MarkAsDataBound();
this.OnDataBound(EventArgs.Empty);
}

并且没有调用父类的方法……这也说明了,ListControl之下的几个控件BulletedListCheckBoxListDropDownListListBoxRadioButtonList,全部都存在同样的问题,当然,解决方法也是一样的。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏xingoo, 一个梦想做发明家的程序员

Oozie分布式工作流——从理论和实践分析使用节点间的参数传递

Oozie支持Java Action,因此可以自定义很多的功能。本篇就从理论和实践两方面介绍下Java Action的妙用,另外还涉及到oozie中actio...

38950
来自专栏Golang语言社区

网络后台开发面试题

1.C++模板的作用。 将算法与具体对象分离,与类型无关,通用,节省精力 2.socket编程,如果client断电了,服务器如何快速知道??? 有以下几个...

69680
来自专栏Kevin-ZhangCG

二十三种设计模式总结

定义:Ensure a class has only one instance, and provide a global point of access to...

12120
来自专栏逆向技术

16位汇编第八讲指令第四讲

        16位汇编第八讲指令第四讲 一丶串操作类指令 1.什么是串操作?   1.串操作指令是8086指令系统中比较独特的一类指令,采用比较特殊的数据串...

21160
来自专栏大内老A

采用一个自创的"验证框架"实现对数据实体的验证[设计篇]

没有想到自己头脑发热写了一个简陋版本的所谓“验证框架”能够得到众多网友的推荐。个人觉得这个验证框架有两个主要的特点是:提供CompositeValidator使...

21380
来自专栏nnngu

记录某公司(简称SMKJ) 的一次面试

昨天去了一家公司面试 Java 开发岗位,这篇文章主要是做一个面试的记录以及总结。 这家公司的规模大概100-200人,环境还可以,在一栋大厦租了两层办公室(3...

33160
来自专栏Android常用基础

Android中的ClassLoader分析

Dalvik是Google公司自己设计用于Android平台的Java虚拟机。它可以支持已转换为.dex(即Dalvik Executable)格式的Java应...

39710
来自专栏恰童鞋骚年

设计模式的征途—17.模板方法(Template Method)模式

在现实生活中,很多事情都需要经过几个步骤才能完成,例如请客吃饭,无论吃什么,一般都包含:点单、吃东西、买单等几个步骤,通常情况下这几个步骤的次序是:点单=>吃东...

10630
来自专栏简书专栏

MongoDB入门

NoSQL,指的是非关系型的数据库。NoSQL有时也称作Not Only SQL的缩写,是对不同的传统的关系型数据库的数据库管理系统的统称。 NoSQL用于超...

21640
来自专栏大内老A

WCF技术剖析之十九:深度剖析消息编码(Encoding)实现(上篇)

消息作为WCF进行通信的唯一媒介,最终需要通过写入传输层进行传递。而对消息进行传输的一个前提或者是一项必不可少的工作是对消息进行相应的编码。WCF提供了一系列可...

19960

扫码关注云+社区

领取腾讯云代金券