解决DropDownList常见问题三则

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

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>
         protected   override   void  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方法

代码
protected   override   void  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

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

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

 

两年多没写博客了,最近对技术,有点伤感!

我不相信神话,我只相信汗水!我不相信命运,我只相信双手!
相关文章
|
3月前
|
C# 开发者 Windows
震撼发布:全面解析WPF中的打印功能——从基础设置到高级定制,带你一步步实现直接打印文档的完整流程,让你的WPF应用程序瞬间升级,掌握这一技能,轻松应对各种打印需求,彻底告别打印难题!
【8月更文挑战第31天】打印功能在许多WPF应用中不可或缺,尤其在需要生成纸质文档时。WPF提供了强大的打印支持,通过`PrintDialog`等类简化了打印集成。本文将详细介绍如何在WPF应用中实现直接打印文档的功能,并通过具体示例代码展示其实现过程。
234 0
|
存储 小程序 前端开发
【易售小程序项目】小程序私聊页面完善(带尾巴聊天气泡组件封装、滑至顶端获取历史聊天数据逻辑优化)【后端基于若依管理系统开发】
【易售小程序项目】小程序私聊页面完善(带尾巴聊天气泡组件封装、滑至顶端获取历史聊天数据逻辑优化)【后端基于若依管理系统开发】
61 0
|
JSON 前端开发 JavaScript
授人以渔 - 如何查找 SAP UI5 官网上没有提到的控件属性的使用明细试读版
授人以渔 - 如何查找 SAP UI5 官网上没有提到的控件属性的使用明细试读版
|
JSON 数据格式
通过一个具体的例子,深入了解 SAP UI5 控件数据双向绑定的工作原理和问题排查方法试读版
通过一个具体的例子,深入了解 SAP UI5 控件数据双向绑定的工作原理和问题排查方法试读版
|
Web App开发 前端开发 JavaScript
使用函数节流思想避免 SAP UI5 应用里按钮短时间内被高频重复点击试读版
使用函数节流思想避免 SAP UI5 应用里按钮短时间内被高频重复点击试读版
|
小程序 UED 开发者
小程序开发必备功能的吐血整理【个人中心界面样式大全】
小程序开发必备功能的吐血整理【个人中心界面样式大全】
650 1
小程序开发必备功能的吐血整理【个人中心界面样式大全】
|
JavaScript
好客租房139-长列表性能优化(懒渲染)
好客租房139-长列表性能优化(懒渲染)
168 0
|
数据处理
【氚云】关于数据隐藏的3个实用技巧,用过的都说好!
今天分享的是如何批量去除空白行和列,也是个简单好用的小技巧,能在不经意间节省时间,提升效率,早点下班!
745 0
【氚云】关于数据隐藏的3个实用技巧,用过的都说好!
|
JavaScript Android开发 iOS开发
第二十五章:页面变化(四)
您自己的用户界面如果您想提供自己的用户界面以在主视图和详细视图之间切换,您可能还希望禁用MasterDetailPage自动提供的界面。您可以通过两种方式执行此操作: 将IsGestureEnabled属性设置为false以禁用iOS和Android上的滑动手势支持。
587 0