我写了一个组件,实现DropDownList的扩展,即可以绑定数据源,实现多列下拉。这里用了孟子的js
事实上它是一个组和控件。
问题一:在 !ispostBack() 中使用它的话,提交后就失去原先绑定的数据了。  
问题二:它的值取不出,就是说点提交按钮后 想取这个组合控件的选取的值,即--那个textbox
的值,每次都为空,我估计第一个问题解决后,第二个问题也会迎刃而解。
问题三:怎样实现在外部绑定,就是说在程序中  DataBind() 而不在组合控件中 DataBind() ;
============================ExtraDropDowmList.cs=======================================
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.ComponentModel;
using System.Web.UI.Design;
using System.Web.UI.Design.WebControls;
namespace Windy
{
/// <summary>
/// ExtraDropDownList 的摘要说明。
/// </summary>
// [
// Designer(typeof(System.Web.UI.Design.WebControls.DataGridDesigner)),
// ValidationProperty("Text"),
// ]
public class ExtraDropDownList :System.Web.UI.WebControls.WebControl
{
public ExtraDropDownList()
{
dgrd.ItemDataBound += new DataGridItemEventHandler(dgrd_ItemDataBound);
}
private DataGrid dgrd = new DataGrid();//创建一个DataGrid
private TextBox txtMain = new TextBox();//创建一个TextBox用来存储选择的值
private HtmlInputHidden hideInput = new HtmlInputHidden();//创建一个隐藏域用来存值
TableCell tc1 = new TableCell();


private const string MOUSE_SCRIPT = //用来触发鼠标事件的脚本
"<script> \n" +
"var dropShow=false\n" +
"var currentID\n" +
"function dropdown(el)\n" +
"{\n" +
"if(dropShow)\n" +
"{\n" +
"dropFadeOut()\n" +
"}\n" +
"else\n" +
"{\n" +
"currentID=el\n" +
"el.style.visibility='visible' \n" +
"dropFadeIn()\n" +
"}\n" +
"}\n" +
"function dropFadeIn()\n" +
"{\n" +//选单淡入的效果
"if(currentID.filters.alpha.opacity<100) \n" +
"{\n" +
"currentID.filters.alpha.opacity+=20 \n" +
"fadeTimer=setTimeout('dropFadeIn()',50)\n" +
"}\n" +
"else\n" +
"{\n" +
"dropShow=true\n" +
"clearTimeout(fadeTimer)\n" +
"}\n" +
"}\n" +
"function dropFadeOut()\n" +
"{\n" +//选单淡出的效果
"if(currentID.filters.alpha.opacity>0)\n" +
"{\n" +
"clearTimeout(fadeTimer)\n" +
"currentID.filters.alpha.opacity-=20\n" +
"fadeTimer=setTimeout('dropFadeOut()',50)\n" +
"}\n" +
"else\n" +
"{\n" +
"dropShow=false\n" +
"currentID.style.visibility='hidden'\n" +
"}\n" +
"}\n" +
"function dropdownHide()\n" +
"{\n" +
"if(dropShow)\n" +
"{\n" +
"dropFadeOut()\n" +
"dropShow=false\n" +
"}\n" +
"}\n" +
"function hiLight(el)\n" +
"{\n" +//高亮度显示指标位置
"if(dropShow)\n" +
"{\n" +
"for(i=0;i<el.parentElement.childNodes.length;i++)\n" +
"{\n" +
"el.parentElement.childNodes(i).className='link_record0'\n" +
"}\n" +
"el.className='link_record1'\n" +
"}\n" +
"}\n" +
"function CheckMe(el)\n" +
"{\n" +//替换显示内容
"document.all.text1.innerText=el.innerText\n" +
"}\n" +
"document.onclick=dropdownHide\n" +
" </script>";
private const string CUSTOMER_STYLE=
@"<style>
BODY { FONT: 12px 宋体 }
TD { FONT: 12px 宋体 }
DIV { FONT: 12px 宋体 }
LABEL { PADDING-RIGHT: 0px; PADDING-LEFT: 4px; PADDING-BOTTOM: 0px; PADDING-TOP: 3px; HEIGHT: 19px }
.link_box { CURSOR: default; TEXT-ALIGN: left }
.link_head { BORDER-RIGHT: 2px inset; BORDER-TOP: 2px inset; BORDER-LEFT: 2px inset; WIDTH: 100%; BORDER-BOTTOM: 2px inset; HEIGHT: 23px }
.link_text { PADDING-LEFT: 2px; BACKGROUND: #fff }
.link_arrow0 { BORDER-RIGHT: 2px outset; BORDER-TOP: 2px outset; BACKGROUND: buttonface; FONT: 14px marlett; BORDER-LEFT: 2px outset; WIDTH: 22px; BORDER-BOTTOM: 2px outset; HEIGHT: 100%; TEXT-ALIGN: center }
.link_arrow1 { BORDER-RIGHT: buttonshadow 1px solid; PADDING-RIGHT: 0px; BORDER-TOP: buttonshadow 1px solid; PADDING-LEFT: 2px; BACKGROUND: buttonface; PADDING-BOTTOM: 0px; FONT: 14px marlett; BORDER-LEFT: buttonshadow 1px solid; WIDTH: 22px; PADDING-TOP: 2px; BORDER-BOTTOM: buttonshadow 1px solid; HEIGHT: 100%; TEXT-ALIGN: center }
.link_value { BORDER-RIGHT: 1px solid; BORDER-TOP: 1px solid; FILTER: alpha(opacity:0); VISIBILITY: hidden; OVERFLOW-X: hidden; OVERFLOW: auto; BORDER-LEFT: 1px solid; BORDER-BOTTOM: 1px solid; POSITION: absolute }
.link_record0 { BORDER-TOP: #eee 1px solid; PADDING-LEFT: 2px; BACKGROUND: #fff; WIDTH: 100%; COLOR: #000; HEIGHT: 20px }
.link_record1 { BORDER-TOP: #047 1px solid; PADDING-LEFT: 2px; BACKGROUND: #058; WIDTH: 100%; COLOR: #fe0; HEIGHT: 20px }
</style>";
//定义属性
/// <summary>
/// override datasource  .
/// </summary>
// [
// Description("override datasource."),
// Category("Appearance"),
// Bindable(true),
// DefaultValue("")
// ]
public object DataSource
{
get
{
return dgrd.DataSource;
}
set
{
dgrd.DataSource = value;
dgrd.DataBind();
}
}
public string SelectedValue
{
get
{
return hideInput.Value;
}
set
{
hideInput.Value = value;
}
}
private void CreateControls()//创建控件以及设置控件的相关属性
{
//创建一个大table-----------------------------
Table container_t = new Table();
container_t.Width=10;
//container_t.BorderWidth=1;
//添加样式,用来控制字体
container_t.Style.Add("font-size","10pt");
//添加大Table一行
TableRow container_tr = new TableRow();
//添加两个单元格,放DataGrid的
TableCell container_tc1 = new TableCell();
container_tc1.CssClass="link_head";
container_tc1.Attributes.Add("onselectstart","return false");
container_tc1.Attributes.Add("onclick","dropdown("+"value1"+")");
//container_tc1.Style.Add("WIDTH","100%"); //放Input 的
TableCell container_tc2 = new TableCell();

//创建一个小table------------------------------
Table t = new Table();
//t.Height=Unit.Parse("100%");
//t.Width= Unit.Parse("100%");
t.CellSpacing=0;
t.CellPadding=0;
t.BorderWidth=0;
//添加小Table一行
TableRow tr = new TableRow();
//添加俩单元格
TableCell tc1 = new TableCell();
tc1.Wrap=false;
txtMain.ID = "text1";
txtMain.Text = "请选择";
txtMain.Width = Unit.Parse("100");
tc1.Controls.Add(txtMain); TableCell tc2 = new TableCell();
tc2.HorizontalAlign=System.Web.UI.WebControls.HorizontalAlign.Right;
//tc2.Width=22;
HtmlAnchor a=new HtmlAnchor();
a.InnerText="6";
a.Attributes.Add("onmouseup","this.className='link_arrow0'");
a.Attributes.Add("class","link_arrow0");
a.Attributes.Add("onmousedown","this.className='link_arrow1'");
a.Attributes.Add("onmouseout","this.className='link_arrow0'");
tc2.Controls.Add(a);

tr.Controls.Add(tc1);
tr.Controls.Add(tc2);
t.Controls.Add(tr); //dgrd所在的a
HtmlAnchor adgrd=new HtmlAnchor();
adgrd.Attributes.Add("class","link_value");
//adgrd.Style.Add("WIDTH","500");
//adgrd.Style.Add("HEIGHT","300");
adgrd.ID="value1";
adgrd.Controls.Add(dgrd);
hideInput.ID = "hideValue"; //将控件添加到Controls集中.
container_tc1.Controls.Add(t);
container_tc1.Controls.Add(adgrd);
container_tc2.Controls.Add(hideInput);
container_tr.Controls.Add(container_tc1);
container_tr.Controls.Add(container_tc2);

container_t.Controls.Add(container_tr);
this.Controls.Add(container_t);  

}
下面继续---

解决方案 »

  1.   

    protected override void CreateChildControls()
    {
    this.EnsureChildControls();//如果子控件没有创建,则创建
    base.CreateChildControls();//调用方法
    CreateControls();
    } protected override void AddAttributesToRender(HtmlTextWriter writer)
    {
    this.EnsureChildControls();
    base.AddAttributesToRender (writer);
    writer.AddStyleAttribute("font-size","9pt");
    }
    protected override void OnPreRender(EventArgs e)
    {
    //将脚本与样式输出到页面中.
    if(!Page.IsClientScriptBlockRegistered("mousescript")) //防止重复输出.
    {
    Page.RegisterClientScriptBlock("mousescript",MOUSE_SCRIPT);
    Page.RegisterClientScriptBlock("customerstyle",CUSTOMER_STYLE);
    }
    base.OnPreRender (e);
    }
    private void dgrd_ItemDataBound(object sender, DataGridItemEventArgs e)
    {
    if( e.Item.ItemIndex != -1 )
    {
    e.Item.Attributes.Add("onmouseover", "this.bgColor='#C1D2EE'");
    e.Item.Attributes.Add("onclick", 
    "document.all.text1.innerText=this.cells[0].innerText;document.all.hideValue.value=this.cells[0].innerText;");
    if (e.Item.ItemIndex % 2 == 0 )
    {
    e.Item.Attributes.Add("bgcolor", "#FFFFFF");
    e.Item.Attributes.Add("onmouseout", "this.bgColor='#ffcccc'");
    }
    else
    {
    e.Item.Attributes.Add("bgcolor", "oldlace");
    e.Item.Attributes.Add("onmouseout", "this.bgColor='#ffcccc'");
    }
    } }
    }
    }
    ==========================Test.aspx.cs 这是测试它的页面的代码================= protected System.Web.UI.WebControls.Button Button1;
    protected Windy.ExtraDropDownList ExtraDropDownList1;

    private void Page_Load(object sender, System.EventArgs e)
    {
    if(!IsPostBack)
    {
    DataSet ds=new DataSet();
    DataTable dt=new DataTable();
    dt.Columns.Add(new DataColumn("列名" ,typeof(String))); DataRow dr=dt.NewRow();
    dr[0] ="aaaaaaaaa";
    dt.Rows.Add(dr); DataRow dr1=dt.NewRow();
    dr1[0] ="bbbbbb";
    dt.Rows.Add(dr1); DataRow dr2=dt.NewRow();
    dr2[0] ="ccccc";
    dt.Rows.Add(dr2); ds.Tables.Add(dt);
    ExtraDropDownList1.DataSource =ds;


    }
      

  2.   

    动态创建的控件保存值可参考
    http://msdn.microsoft.com/workshop/author/tables/buildtables.asp
    用隐藏的input传递值应该比较好,可以用Request.Form["HiddenInputName"]得到值,应该没有什么问题的
    http://dotnet.aspx.cc/ShowDetail.aspx?id=E6E35E3C-2C28-4DAD-ACBB-DB78D2785776
      

  3.   

    孟子大哥。 你说的 Request.Form["HiddenInputName"]得到值
    也不是很完美呀。我开发的组件会用着很不方便的,我看有的组件就很方便。
    而且
    动态创建的控件保存值可参考
    http://msdn.microsoft.com/workshop/author/tables/buildtables.asp
    这个不对呀,是创建 table的。
      

  4.   

    在回传(postback)后需要重新绑定数据源。
      

  5.   

    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconpostbackdataprocessingsample.asp
      

  6.   

    server controls are very complicated, you should start with some simple controls first, then move onto complicated ones1. you should implement INamingContainer:
    public class ExtraDropDownList :System.Web.UI.WebControls.WebControl, INamingContainerbut that will break all your javascriptfor now, try this<%@ Import Namespace="System.Data" %>
    <%@ Register TagPrefix="cc" Assembly="ExtraDDL" Namespace="Windy" %>
    <form runat="server">
     <asp:Button id="Button1" runat="server" Text="Submit" OnClick="Button_Click"/>
     <cc:ExtraDropDownList id="ExtraDropDownList1" runat="server"/>
    </form>
    <script language="C#" runat="server">

    private void Page_Load(object sender, System.EventArgs e)
    {
    if(!IsPostBack)
    {
    DataSet ds=new DataSet();
    DataTable dt=new DataTable();
    dt.Columns.Add(new DataColumn("列名" ,typeof(String))); DataRow dr=dt.NewRow();
    dr[0] ="aaaaaaaaa";
    dt.Rows.Add(dr); DataRow dr1=dt.NewRow();
    dr1[0] ="bbbbbb";
    dt.Rows.Add(dr1); DataRow dr2=dt.NewRow();
    dr2[0] ="ccccc";
    dt.Rows.Add(dr2); ds.Tables.Add(dt);
    ExtraDropDownList1.DataSource =dt.DefaultView;
    ExtraDropDownList1.DataBind();

    } ExtraDropDownList1.SelectedValue = "xx"; }void Button_Click(object sender, System.EventArgs e)
    {
    Response.Write("In Button_Click:" + ExtraDropDownList1.SelectedValue +"<BR>");
    }</script>2.as for the first one, try public object DataSource
    {
    get
    {
    return dgrd.DataSource;
    }
    set
    {
    dgrd.DataSource = value;
    }
    }
    public string SelectedValue
    {
    get
    {
    EnsureChildControls();
    return hideInput.Value;
    }
    set
    {
    EnsureChildControls();
    hideInput.Value = value;
    }
    }
    public override void DataBind() 
    {
           CreateControls();
           if (DataSource != null)
    dgrd.DataBind(); ChildControlsCreated = true;
    } protected override void CreateChildControls()
    {
    CreateControls();
    } protected override void AddAttributesToRender(HtmlTextWriter writer)
    {
    base.AddAttributesToRender (writer);
    writer.AddStyleAttribute("font-size","9pt");
    }
      

  7.   

    如果你用上述的编码,我测试过得,应该可以看到你的数据postback之后还是会保存,虽然有时会有脚本错误但归根到底,你的想法太简单了,常规的做法是实现INamingContainer
      

  8.   

    我在开发菜单控件时也遇到如此问题,参考方案如下:
    重写控件的SaveViewState()和LoadViewState方法
    protected override object SaveViewState()
    {
    object baseState = base.SaveViewState();
    object textState = new object();
    object[] myState = new object[3]; myState[0] = baseState;
    myState[1] = outCssClass;
    myState[2] = overCssClass;

    return myState;
    }protected override void LoadViewState(object savedState)
    {
    if(savedState != null)
    {
    object[] myState = (object[])savedState; if(myState[0] != null)
    base.LoadViewState(myState[0]); if(myState[1] != null)
    outCssClass = (string)myState[1]; if(myState[2] != null)
    overCssClass = (string)myState[2];
    }
    }
      

  9.   

    xiexie 楼上的我回去试一下
      

  10.   

    思归的方法果然不错那么,
    1. you should implement INamingContainer:
    public class ExtraDropDownList :System.Web.UI.WebControls.WebControl, INamingContainerbut that will break all your javascript
    这个我必须用js来传递值。该怎么办?
      

  11.   

    试着输出正确的ID,譬如(没测试,所以可能有错),把你的MOUSE_SCRIPT,其中的这行document.all.text1.innerText=el.innerTex
    改成
    document.all('{0}').innerText=el.innerTex你也需要把"{"变成"{{","}"变成"}}"然后Page.RegisterClientScriptBlock("mousescript",String.Format(MOUSE_SCRIPT, 
    txtMain.ClientID));
      

  12.   

    强力顶  saucer(思归)
    果然很强,学到了不少。问题全部解决!