📄 twoleveldropdownlist.cs
字号:
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Data;
using System.Text;
namespace X2Design.UI
{
/// <summary>
/// 提供两层菜单的联动,联动逻辑在客户端用Javascript实现,不会出现回传现象。
/// 当前缺点:若产生两个同样的联动菜单,则客户端代码会产生两份冗余。但不会冲突,可正常使用。
/// </summary>
public class TwoLevelDropDownList:Control
{
/// <summary>
/// 主下拉框。
/// </summary>
protected System.Web.UI.WebControls.DropDownList ddl1;
/// <summary>
/// 从下拉框。
/// </summary>
protected System.Web.UI.WebControls.DropDownList ddl2;
/// <summary>
///
/// </summary>
protected DataTable dt1;
/// <summary>
///
/// </summary>
protected DataTable dt2;
/// <summary>
/// 获取或者设置数据源。
/// </summary>
public virtual DataTable DataSource
{
get
{
DataTable d=(DataTable)ViewState["DataSource"];
return d;
}
set
{
ViewState["DataSource"]=value;
}
}
/// <summary>
/// 获取或者设置显示的文字字段
/// </summary>
public virtual string DataTextField
{
get
{
string s=(string)ViewState["DataTextField"];
return (s==null)?String.Empty:s;
}
set
{
ViewState["DataTextField"]=value;
}
}
/// <summary>
/// 获取或者设置值字段。
/// </summary>
public virtual string DataValueField
{
get
{
string s=(string)ViewState["DataValueField"];
return (s==null)?String.Empty:s;
}
set
{
ViewState["DataValueField"]=value;
}
}
/// <summary>
/// 获取或者设置从下拉框的主键字段名称,对应于主下拉框的主键字段。
/// </summary>
public virtual string SecondKeyField
{
get
{
string s=(string)ViewState["SecondKeyField"];
return (s==null)?String.Empty:s;
}
set
{
ViewState["SecondKeyField"]=value;
}
}
/// <summary>
/// 获取或设置选项的层次(1表示主下拉框,2表示从下拉框)。
/// </summary>
public virtual string LevelField
{
get
{
string s=(string)ViewState["LevelField"];
return (s==null)?String.Empty:s;
}
set
{
ViewState["LevelField"]=value;
}
}
/// <summary>
/// 主下拉框的标题
/// </summary>
public virtual string FirstTitle
{
get
{
string s=(string)ViewState["FirstTitle"];
return (s==null)?String.Empty:s;
}
set
{
ViewState["FirstTitle"]=value;
}
}
/// <summary>
/// 从下拉框的标题
/// </summary>
public virtual string SecondTitle
{
get
{
string s=(string)ViewState["SecondTitle"];
return (s==null)?String.Empty:s;
}
set
{
ViewState["SecondTitle"]=value;
}
}
/// <summary>
/// 获取或者设置主下拉框的值。对应于下拉框的值字段。
/// </summary>
public virtual string FirstValue
{
get
{
if(this.Page.IsPostBack)
{
return this.Page.Request.Form[ddl1.ClientID].ToString();
}
string s=(string)ViewState["FirstValue"];
return (s==null)?"0":s;
}
set
{
ViewState["FirstValue"]=value;
}
}
/// <summary>
/// 获取或者设置从下拉框的值。对应于下拉框的值字段。
/// </summary>
public virtual string SecondValue
{
get
{
if(this.Page.IsPostBack)
{
return this.Page.Request.Form[ddl2.ClientID].ToString();
}
string s=(string)ViewState["SecondValue"];
return (s==null)?"0":s;
}
set
{
ViewState["SecondValue"]=value;
}
}
/// <summary>
/// 产生客户端脚本。
/// </summary>
/// <param name="htw">HtmlTextWriter。用于写文件。</param>
protected void GenInitScript(HtmlTextWriter htw)
{
//根据第一个选项值生成第二个下拉框所有选项的脚本
htw.Write("<script language=javascript>");
htw.Write("GetOptions_");
htw.Write(this.ID);
htw.Write("(\"");
htw.Write(this.FirstValue);
htw.Write("\",document.getElementById(\"");
htw.Write(ddl2.ClientID);
htw.Write("\"));\n");
//根据第二个下拉框指定值生成选中的脚本
htw.Write("SetTheOther_"+this.ID+"(document.getElementById(\"");
htw.Write(ddl2.ClientID);
htw.Write("\"),\"");
htw.Write(this.SecondValue);
htw.Write("\");\n");
htw.Write("</script>");
}
/// <summary>
/// 产生级联菜单的客户端脚本。
/// </summary>
/// <param name="htw">HtmlTextWriter。用于写文件。</param>
protected void GenClientScript(HtmlTextWriter htw)
{
//StringBuilder sbScript=new StringBuilder();
htw.Write("<script language=javascript><!--\n");
//获得下拉框二的选项
htw.Write("function GetOptions_" + this.ID + "(value1,ddl2)\n");
htw.Write("{\n");
htw.Write(" switch(value1)\n");
htw.Write(" {\n");
for(int i=0;i<dt1.Rows.Count;i++)
{
htw.Write(" case \"");
htw.Write(dt1.Rows[i][this.DataValueField].ToString());
htw.Write("\":\n");
htw.Write(" var OptionArray=new Array(");
for(int j=0;j<dt2.Rows.Count;j++)
{
if(dt2.Rows[j][this.SecondKeyField].ToString()==dt1.Rows[i][this.DataValueField].ToString())
{
htw.Write("\"");
htw.Write(dt2.Rows[j][this.DataTextField].ToString());
htw.Write("\",");
htw.Write("\"");
htw.Write(dt2.Rows[j][this.DataValueField].ToString());
htw.Write("\",\n");
}
}
htw.Write("\"0\",\"0\");\n");
htw.Write(" break;\n");
}
htw.Write("default:\n var OptionArray=new Array(\"0\",\"0\");\nbreak;");
htw.Write("}\n");
htw.Write("ClearDdl_"+this.ID+"(ddl2);\n");
htw.Write("var x=0;\n");
htw.Write("for(var i=0;i<OptionArray.length-2;i=i+2)\n{\nx++;\n");
htw.Write("ddl2.options[x]=new Option(OptionArray[i],OptionArray[i+1]);\n}\n}\n");
//以下函数仅需出现一次
//设置第二个下拉框的选项
htw.Write("function SetTheOther_"+this.ID+"(ddl2,value2)\n");
htw.Write("{\n");
htw.Write("for(var i=0;i<ddl2.options.length;i++)\n");
htw.Write("{\n");
htw.Write(" if(ddl2.options[i].value==value2)\n");
htw.Write(" {\n");
htw.Write(" ddl2.options[i].selected=true;\n");
htw.Write(" break;\n");
htw.Write(" }\n}\n}\n");
//清空下拉框
htw.Write("function ClearDdl_"+this.ID+"(ddl){\n");
htw.Write("for(var i=1;i<ddl.options.length;i++){ddl.options[i]=null;}}\n");
htw.Write("--></script>");
}
/// <summary>
/// 构造函数。
/// </summary>
public TwoLevelDropDownList()
{
this.PreRender+=new EventHandler(this.RelationDropDownList_PreRender);
this.Init+=new EventHandler(RelationDropDownList_Init);
}
/// <summary>
/// 生成控件。覆盖基类的Render方法。
/// </summary>
/// <param name="htw">HtmlTextWriter。用于写文件。</param>
protected override void Render(HtmlTextWriter htw)
{
this.GenClientScript(htw);
ddl1.RenderControl(htw);
ddl2.RenderControl(htw);
//产生进行预处理的客户端脚本
this.GenInitScript(htw);
}
/// <summary>
/// 绑定数据源,触发绑定事件。
/// </summary>
public override void DataBind()
{
base.OnDataBinding(EventArgs.Empty);
}
/// <summary>
/// 自定义的绑定逻辑。
/// </summary>
protected void MyBind()
{
dt1=this.DataSource.Copy();
dt2=dt1.Clone();
//将两级目录分开到两个数据表中
for(int i=0;i<dt1.Rows.Count;i++)
{
DataRow dr1=dt1.Rows[i];
if(dr1[this.LevelField].ToString()!="0")
{
DataRow dr2=dt2.NewRow();
for(int j=0;j<dt2.Columns.Count;j++)
{
dr2[j]=dr1[j];
}
dt2.Rows.Add(dr2);
dt1.Rows.Remove(dr1);
i--;
}
}
ddl1.DataSource=dt1;
ddl1.DataTextField=this.DataTextField;
ddl1.DataValueField=this.DataValueField;
ddl1.DataBind();
}
/// <summary>
/// 在调用前产生客户端脚本否则不能获得下拉框客户端id。
/// </summary>
/// <param name="sender">事件源。</param>
/// <param name="e">事件参数。</param>
private void RelationDropDownList_PreRender(object sender, EventArgs e)
{
this.MyBind();
this.SetTitle();
//设置下拉框一的选项
ddl1.ClearSelection();
ListItem li0=ddl1.Items.FindByValue(this.FirstValue);
if(li0!=null)
{
li0.Selected=true;
}
else
{
throw new ArgumentException("The value doesn't exist!");
}
ddl1.Attributes.Add("OnChange","GetOptions_"+this.ID+"(this.options[this.selectedIndex].value," + ddl2.ClientID + ");");
}
/// <summary>
/// 根据指定的主从下拉框标题产生下拉框。
/// </summary>
protected void SetTitle()
{
ddl1.Items.Insert(0,new ListItem(this.FirstTitle,"0"));
ddl2.Items.Insert(0,new ListItem(this.SecondTitle,"0"));
}
/// <summary>
/// 控件初始化时执行
/// </summary>
/// <param name="sender">事件源。</param>
/// <param name="e">事件参数。</param>
private void RelationDropDownList_Init(object sender, EventArgs e)
{
this.Controls.Clear();
ddl1=new DropDownList();
ddl2=new DropDownList();
ddl1.EnableViewState=false;
ddl2.EnableViewState=false;
//初始化唯一名字
ddl1.ID="x2ddl11_"+this.ID;
ddl2.ID="x2dd1l2_"+this.ID;
//当页面回传时得到两个选中的个值
if(this.Page.IsPostBack)
{
FirstValue=this.Page.Request.Form[ddl1.ClientID].ToString();
SecondValue=this.Page.Request.Form[ddl2.ClientID].ToString();
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -