推荐.NET教程: ASP.NET C# 开发环境 Ajax教程 控件开发 统计报表 数据库 Web服务 安装部署 CommunityServer NHibernate DataGrid/GridView 实用代码 VS2005
示例源码 MVC/三层 SqlHelper 入门源码 开源 CMS Ajax/Atlas C#.net 毕业设计 源码 经典代码 商业 本站作品 持久层 随书源码 WebService 英文/汉化 Asp.net2.0

阿牛·乐园

每天进步一点点

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  71 随笔 :: 14 文章 :: 377 评论 :: 13 引用
自己好几个地方要用到联动控件,项目又不想用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>(