简单好用的联动下拉控件(修正)

自己好几个地方要用到联动控件,项目又不想用Ajax,又想在客户端实现联动而不刷新,还想在服务器端用相似的代码来绑定项,还想在服务器端用相同的代码得到选定的值(也就是值可以提交),想了想,还是写一个控件好了.

以国家,省,市举例,我的实现思路是,
1.把所有国家绑定到国家列表,把所有的省绑定在省列表(包括各各国家),把所以的市绑定在市列表(包括所有的市).
2. 在客户端,用脚本把省,市和各项分组并保存,然后从 select.options 里去除不需要的option.

  修正不能在同页面有多个联动的BUG

代码如下:
1. 控件代码:
namespace Iyond.Web.UI.WebControls
{
    
public class RelationDropDownList : System.Web.UI.WebControls.DropDownList
    
{
        
protected ValueParentValueDictionary valueParentValues = new ValueParentValueDictionary();

        [DescriptionAttribute(
"ParentDropDownListControl"), IDReferenceProperty, TypeConverter(typeof(RelationDropDownListControlConverter)), Themeable(false), DefaultValue(""), CategoryAttribute("Behavior")]
        
public string ParentDropDownListControl
        
{
            
get
            
{
                
object obj1 = this.ViewState["ParentDropDownListControl"];
                
if (obj1 != null)
                
{
                    
return (string)obj1;
                }

                
return string.Empty;
            }

            
set
            
{
                
this.ViewState["ParentDropDownListControl"= value;
            }

        }


        [DescriptionAttribute(
"ParentDropDownListControl"), IDReferenceProperty, TypeConverter(typeof(RelationDropDownListControlConverter)), Themeable(false), DefaultValue(""), CategoryAttribute("Behavior")]
        
public string ChildDropDownListControl
        
{
            
get
            
{
                
object obj1 = this.ViewState["ChildDropDownListControl"];
                
if (obj1 != null)
                
{
                    
return (string)obj1;
                }

                
return string.Empty;
            }

            
set
            
{
                
this.ViewState["ChildDropDownListControl"= value;
            }

        }



        [DescriptionAttribute(
"DataParentValueField"), Themeable(false), DefaultValue(""), CategoryAttribute("Data")]
        
public virtual string DataParentValueField
        
{
            
get
            
{
                
object obj2 = this.ViewState["ParentDataValueField"];
                
if (obj2 != null)
                
{
                    
return (string)obj2;
                }

                
return string.Empty;
            }

            
set
            
{
                
this.ViewState["ParentDataValueField"= value;
                
if (base.Initialized)
                
{
                    
base.RequiresDataBinding = true;
                }

            }

        }


        
 


        
protected RelationDropDownList ParentDropDownList
        
{
            
get
            
{
                
if (string.IsNullOrEmpty(this.ParentDropDownListControl))
                    
return null;

                
return this.NamingContainer.FindControl(this.ParentDropDownListControl) as RelationDropDownList;
            }

        }


        
protected RelationDropDownList ChildDropDownList
        
{
            
get
            
{
                
if (string.IsNullOrEmpty(this.ChildDropDownListControl))
                    
return null;

                
return this.NamingContainer.FindControl(this.ChildDropDownListControl) as RelationDropDownList;
            }

        }


        
protected override void Render(HtmlTextWriter writer)
        
{

            
base.Render(writer);

            
if (this.ChildDropDownList == null)
            

                
//这是最后一级,依本身的SelectedIndex 来更新上级 修正不能在同页面有多个联动的BUG
                Page.ClientScript.RegisterStartupScript(this.GetType(), this.ClientID + "_relddl_clearUp"string.Format("javascript:relddl_clearUp('{0}');"this.ClientID),true);
            }

        }


        
protected override void OnPreRender(EventArgs e)
        
{
            Page.ClientScript.RegisterClientScriptResource(typeof(RelactionDropDownList)
"Iyond.Web.UI.WebControls.DropDownList.Resources.RelationDDL.js");
            
base.OnPreRender(e);
        }


        
protected override void AddAttributesToRender(HtmlTextWriter writer)
        
{
            
base.AutoPostBack = false;
            
base.AddAttributesToRender(writer);

            writer.AddAttribute(
"parentSelect"this.ParentDropDownList != null?this.ParentDropDownList.ClientID:"");
            writer.AddAttribute(
"childSelect",this.ChildDropDownList != null?this.ChildDropDownList.ClientID: "");


            writer.AddAttribute( HtmlTextWriterAttribute.Onchange, 
"javascript:relddl_onchange(this,event)");
        }


        
protected override void PerformDataBinding(System.Collections.IEnumerable dataSource)
        
{
            
base.PerformDataBinding(dataSource);
            
if (this.ParentDropDownList != null)
            
{
                valueParentValues.Clear();

                
foreach (object obj in dataSource)
                
{
                    
string dataValueField = this.DataValueField;
                    
string parentDataValueField = this.DataParentValueField;
                    
string value = Convert.ToString(DataBinder.GetPropertyValue(obj, dataValueField));
                    
if (valueParentValues.ContainsKey(value))
                    
{
                        
throw new ArgumentException("相关的列表中. DataValueField 字段的值不能重复");
                    }



                    
string parentValue =  Convert.ToString(DataBinder.GetPropertyValue(obj, parentDataValueField));
                    valueParentValues.Add(value, parentValue);
                }


                SetItemParentValue();
            }


        }


        
protected virtual void SetItemParentValue()
        

            
foreach (string value in valueParentValues.Keys)
            
{
                
string parentValue = valueParentValues[value];

                ListItem lt 
= this.Items.FindByValue(value);
                
if (lt != null)
                
{
                    lt.Attributes[
"parentValue"=parentValue;
                }

            }

        }




        
protected override object SaveViewState()
        
{
            
object x = base.SaveViewState();
            
object y = valueParentValues;
            
object z = null;
            
if (((z == null&& (y == null)))
            
{
                
return null;
            }

            
return new Triplet(x, y, z);
        }


        
protected override void LoadViewState(object savedState)
        
{
            
if (savedState != null)
            
{
                Triplet triplet 
= (Triplet)savedState;
                
base.LoadViewState(triplet.First);
                valueParentValues 
= triplet.Second as ValueParentValueDictionary;
                
if (valueParentValues != null)
                
{
                    SetItemParentValue();
                }

            }

            
else
            
{
                
base.LoadViewState(null);
            }

        }


    }


    
public class RelationDropDownListControlConverter : ControlIDConverter
    
{
        
protected override bool FilterControl(Control control)
        
{
            
if (control is RelationDropDownList)
                
return true;
            
else
            
{
                
return false;
            }


        }

    }


    [Serializable]
    
public class ValueParentValueDictionary : Dictionary<stringstring>
    
{
        
public ValueParentValueDictionary()
            :
base()
        
{}

        
public ValueParentValueDictionary(IDictionary<stringstring> dictionary)
            :
base(dictionary)
        
{}
        
public ValueParentValueDictionary(IEqualityComparer<string> comparer)
            :
base(comparer)
        
{}

        
public ValueParentValueDictionary(int capacity)
            :
base(capacity)
        
{}

        
public ValueParentValueDictionary(IDictionary<stringstring> dictionary, IEqualityComparer<string> comparer)
            :
base(dictionary,comparer)
        
{}
        
public ValueParentValueDictionary(int capacity, IEqualityComparer<string> comparer)
            :
base(capacity,comparer)
        
{}
        
protected ValueParentValueDictionary(SerializationInfo info, StreamingContext context)
            :
base(info,context)
        
{}
    }


}

2. 使用举例:
        <iyond:RelationDropDownList ID="ddlCountry" runat="server" ChildDropDownListControl="ddlProvince">
        
</iyond:RelationDropDownList>
        
<iyond:RelationDropDownList ID="ddlProvince" runat="server" ChildDropDownListControl="ddlCity" ParentDropDownListControl="ddlCountry">
        
</iyond:RelationDropDownList>
        
<iyond:RelationDropDownList ID="ddlCity" runat="server" ParentDropDownListControl="ddlProvince">
        
</iyond:RelationDropDownList>
    protected void Page_Load(object sender, EventArgs e)
    
{
        
if (!Page.IsPostBack)
        
{
            List
<ZoneItem> listCountry = new List<ZoneItem>(
                
new ZoneItem[]{
                    
new ZoneItem(1,"中国"),
                    
new ZoneItem(2,"美国")}
);

            List
<ZoneItem> listProvince = new List<ZoneItem>(
                
new ZoneItem[]{
                    
new ZoneItem(1,"河北省",1),
                    
new ZoneItem(2,"河南省",1),
                    
new ZoneItem(3,"加州",2)
                }
);


            List
<ZoneItem> listCity = new List<ZoneItem>(
                
new ZoneItem[]{
                    
new ZoneItem(1,"石家庄",1),
                    
new ZoneItem(2,"邯郸",1),
                    
new ZoneItem(3,"安阳",2),
                    
new ZoneItem(4,"纽约",3)
                }
);


            
this.ddlCountry.DataSource = listCountry;
            
this.ddlCountry.DataTextField = "Name";
            
this.ddlCountry.DataValueField = "Id";
            
this.ddlCountry.DataParentValueField = "ParentId";
            
this.ddlCountry.DataBind();

            
this.ddlProvince.DataSource = listProvince;
            
this.ddlProvince.DataTextField = "Name";
            
this.ddlProvince.DataValueField = "Id";
            
this.ddlProvince.DataParentValueField = "ParentId";
            
this.ddlProvince.DataBind();

            
this.ddlCity.DataSource = listCity;
            
this.ddlCity.DataTextField = "Name";
            
this.ddlCity.DataValueField = "Id";
            
this.ddlCity.DataParentValueField = "ParentId";
            
this.ddlCity.DataBind();

        }

        
else
        
{
            Response.Write(
this.ddlCity.SelectedValue);
        }


    }

3.生成的客户页HTML
<select name="ddlCountry" id="ddlCountry" parentSelect="" childSelect="ddlProvince" onchange="javascript:relddl_onchange(this,event)">
    
<option selected="selected" value="1">中国</option>
    
<option value="2">美国</option>

</select>
        
<select name="ddlProvince" id="ddlProvince" parentSelect="ddlCountry" childSelect="ddlCity" onchange="javascript:relddl_onchange(this,event)">
    
<option selected="selected" value="1" parentValue="1">河北省</option>
    
<option value="2" parentValue="1">河南省</option>
    
<option value="3" parentValue="2">加州</option>

</select>
        
<select name="ddlCity" id="ddlCity" parentSelect="ddlProvince" childSelect="" onchange="javascript:relddl_onchange(this,event)">
    
<option selected="selected" value="1" parentValue="1">石家庄</option>
    
<option value="2" parentValue="1">邯郸</option>
    
<option value="3" parentValue="2">安阳</option>
    
<option value="4" parentValue="3">纽约</option>

</select>

丢了JS了:
//======================================================================
//
         Cutech DropDownList Script 
//
         Version 1.0 Code by Evlon.(evlon@126.com)
//
         Copyright(C)2007-2008 Cutech Co,ltd. All Rights Reserved.
//
=======================================================================
        function relddl_onchange(sender, e)
        
{
            
var selId = sender.childSelect;
            
if(selId == '')
                
return;
                
            
var selectedValue = sender.options[sender.selectedIndex].value;
            
var sel = document.getElementById(selId);
            
if(sel != null)
            
{
                
with(sel)
                
{
                    
//保存选定值
                    if(currentGroupItem != null)
                    
{
                        currentGroupItem[
0= options.selectedIndex;
                    }

                    
                    
var items = groupItems.Item(selectedValue);
                    currentGroupItem 
= items;
                    
                    options.length 
= 0;
                    
if(items != null)
                    
{
                        
if(items.length > 1)
                        
{
                            
for(var i = 1; i < items.length; ++i)
                            
{
                                options.add(items[i]);
                            }

                            
                            options.selectedIndex 
= items[0== -1?0:items[0];
                            
if(options.selectedIndex != -1)
                            
{                           
                                
var e = document.createEventObject();
                                fireEvent(
"onchange");
                            }

                        }

                        
else
                        
{
                            disable 
= true;
                        }

                    }

                }
   
            }

        }

        
        
function relddl_setSelectedValue(selElement, selectedValue)
        
{
            
with(selElement.options)
            
{
                
for(var i = 0; i < length; ++i)
                
{
                    
var lt = item(i);
                    
if(lt.value == selectedValue)
                    
{
                        lt.selected 
= true;
                        
return lt.index;
                    }

                }

            }

        }

        
        
function relddl_initSelect(selElement)
        
{
            
var removeIndex = [];
            
//分组
            with(selElement.options)
            
{
                
var dic = new ActiveXObject("Scripting.Dictionary");
                
var selectedParentValue = item(selectedIndex).parentValue;
                
                setAttribute(
"groupItems",dic);
                setAttribute(
"currentGroupItem",null);
                
for(var i = 0; i < length; ++i)
                
{
                    
var lt = item(i);
                    
if(!dic.Exists(lt.parentValue))
                    
{
                        
if(selectedIndex == i)
                        
{
                            currentGroupItem 
= [selectedIndex];
                            dic.Add(lt.parentValue,currentGroupItem);
                        }

                        
else
                        
{
                            dic.Add(lt.parentValue,[
-1]);
                        }

                    }

                   
                    dic.Item(lt.parentValue).push(lt);
                    
                    
if(lt.parentValue != selectedParentValue)
                    
{
                        removeIndex.push(lt.index);
                    }

                }

                

                
while(removeIndex.length > 0)
                
{
                    remove(removeIndex.pop());
                }

                
                
            }

        }


        
function relddl_clearUp(selectId)
        
{
            
var selId = selectId;
            
var selectedValue = '';
            
for(var i = 0;selId != ''; ++i)
            
{
                
var sel = document.getElementById(selId);
                
if(sel == null)
                    
return ;
                
                
if(i > 0)
                
{
                    
var selectedIndex = relddl_setSelectedValue(sel,selectedValue);
                    
if(selectedIndex == -1)
                        
return;
                }

                relddl_initSelect(sel);
                
                
if(sel.options.length > 0)
                
{
                    selectedValue 
= sel.options[0].parentValue;
                    
if(selectedValue == '')
                        
return;
                }

                selId 
= sel.parentSelect;
            }

        }



最后.欢迎大家拍砖.
QQ:273352165 evlon#126.com 转载请注明出处。
原文地址:https://www.cnblogs.com/evlon/p/671468.html