http://dotnet.aspx.cc/ShowDetail.aspx?id=B131BF6E-B35B-413C-9DCE-E755242FA795按照上面的做法添加的摸伴列,在摸板列里加了一个RadioButtonList控件。在程序中,我用一个动态生成的Web TableCell加载这个动态生成DataGrid
两个问题:
想取出其中的选择并对某种选择进行统计
如果在做某种选择后,想在同一行的RadioButtonList控件列后的另一列显示一个文本框(平时隐藏)
高手有办法吗?

解决方案 »

  1.   

    首先,Datagrid中动态生成的列,ASP.NET不为其维持状态,也就是在Postback后会自动消失,所以要在Page_Load中自己维护动态列;这样就会有个问题,也就是你通过访问Datagrid.Item的方法是拿不到RadioButtonList的选择值的,只会传回RadioButtonList的初始值。
    目前,我所知道的可行的方法,只有在 Page_Load 中,读取 request.form.allkeys 中回传回来的值,这里面会有你RadioButtonList的选择情况,不过这个key并不直观,而是以 datagridname:ctrl1:xxxxxxx 这样以冒号连接的几段字符串来表示的,分别对应Datagrid的ID,Control在Datagrid中的行数,Control的ID,你只能通过自己解析这个字符串来判断RadioButtonList的选择情况。“如果在做某种选择后,想在同一行的RadioButtonList控件列后的另一列显示一个文本框”,如果你是要在这个RadioButtonList选择后再显示这个文本框,我估计也只能用JavaScript来实现了,如果你是点击Datagrid里某个固定列中的控件来显示文本框,那样可以使用Datagrid的EditItemTemplate来实现。
      

  2.   

    回 qzj(SoldierQ):动态生成DataGrid的程序:
    ......
        public TemplateColumn dgc_option=new TemplateColumn();
        public ColumnTemplate myColumn=new ColumnTemplate();
    ......
        public void Button1_Click_1(object sender, System.EventArgs e)
    {
    ..... for (int inti=0; inti<Convert.ToInt32(TextBox1.Text.ToString());inti++)
    {
    ...... 
       TableRow myrow=new TableRow();
                                          TableCell mycell=new TableCell();
                                       
                                          DataGrid DataGrid1=new DataGrid();
    ......
                                         dgc_option.ItemTemplate=myColumn;
    DataGrid1.Columns.Add(dgc_option); 

    DataGrid1.DataBind();
    mycell.Controls.Add(DataGrid1);

    myrow.Cells.Add(mycell);
    Table1.Rows.Add(myrow);  
                   }
                        }
    public class ColumnTemplate : ITemplate      
    {
    public void InstantiateIn(Control container)
    {
    RadioButtonList myRadio=new RadioButtonList();
    myRadio.RepeatDirection=RepeatDirection.Horizontal;
    myRadio.Items.Add("合格");
    myRadio.Items.Add("不合格");
    myRadio.Items.Add("忽略");
    container.Controls.Add(myRadio);
    }
    }
    我都不知道用什么方法给myRadio的ID赋值,能说说吗?
      

  3.   

    RadioButtonList myRadio=new RadioButtonList();myRadio.ID = ........
      

  4.   

    模板列的头
    既然TemplateColumn类给了HeaderTemplate(FooterTemplate)属性,你就可以定制给定列的头(header)和尾(footer)。说到定制,它在这里是非常重要的一点。因为在普通的数据绑定列中没有header模板和footer模板。HeaderTemplat只能应用在TemplateColumn 类的一个实例中。对于这个实例,如果你想用一个非标准的方法编辑该列的内容(例如说你想添加对内容的验证),你可以用headertemplate,也可以用一个简单的BoundColumn类来呈现。
    真的可以改变列的header布局吗?如果你需要根据某个表达式对列进行排序,排序机制是datagrid自动在列的头部插入一个hyperlink控件,当用户单击hyperlink控件时,asp.net会根据hyperlink控件的href属性触发一个回发事件,从而对该列进行排序操作。就算你不需要排序你也可以很自由的更改列的header。如果你需要用ItemCreated事件在header中增加其它的控件及脱离datagrid控件做其它的任何事情。下面请看一个例子:
    Figure 3 Adding the Sort Dropdown 
    public void ItemCreated(Object sender, DataGridItemEventArgs e)
    {
        ListItemType lit = e.Item.ItemType;
        if (lit == ListItemType.Header)
        {
            // Create and fill a dropdown list control
            DropDownList dd = new DropDownList();
            dd.ID = "ddSort";
            ListItem li1, li2, li3;        // ListItem constructor takes Text and Value for the item
            li1 = new ListItem("Title of courtesy", "titleofcourtesy");
            dd.Items.Add(li1);        li2 = new ListItem("Last Name", "lastname");
            dd.Items.Add(li2);        li3 = new ListItem("First Name", "firstname");
            dd.Items.Add(li3);        // Selects the item, if any, that was selected last time
            dd.SelectedIndex = Convert.ToInt32(grid.Attributes["FieldIndex"]);        // Add the dropdown list to the header of the 2nd column
            TableCell cell = (TableCell) e.Item.Controls[1];
            cell.Controls.Add(dd);
        }
    }public void SortCommand(Object sender, DataGridSortCommandEventArgs e)
    {
        // Code that retrieves the grid's data source GOES HERE
        &#8226;&#8226;&#8226;    // Sort by the specified expression or figure it out 
        if (e.SortExpression != "*")
            dv.Sort = e.SortExpression;
        else
        {
            // Retrieves the dropdown list control through its ID 
            DataGridItem dgi = (DataGridItem) e.CommandSource;
            DropDownList dd = (DropDownList) dgi.FindControl("ddSort");        // Retrieves the sorting expression from the list
            dv.Sort = dd.SelectedItem.Value;         // Persists the currently selected dropdown item
            grid.Attributes["FieldIndex"] = dd.SelectedIndex.ToString();
        }
        
        // Refreshes the grid
        grid.DataBind();
    }
      

  5.   


    实现ITemplate
    如果你想完全地在内存中创建一个的模板,你不得不首先编码,然后实例化一个类,该类实现ITemplate接口. ITemplate接口只有一个方法,名为InstantiateIn. asp.net中所有具有template属性的服务器控件都通过这个属性暴露实现了ITemplate接口的类.这个接口简单地定义了用于组合与模板一致的子控件的实例的方法来填充容器控件.图11演示了实现itemplate接口大部分的代码,它为一个datagrid在内存中创建了一个的模板列.同样,也可以把这些代码用于datalist和repeater控件中。唯一不同的是在OnDataBinding事件处理上。类的结构你可以写成类似下面:
    class LastFirstNameTemplate : ITemplate
    {
      public void InstantiateIn(Control container) 
      {...}  private void BindLastName(Object s, EventArgs e)
      {...}  private void BindFirstName(Object s, EventArgs e)
      {...}
    }Figure 11 In-memory Templated Column 
    // 动态的创建模板列函数
    public void AddTemplateColumnFromITemplate(String strHeader)
    {
        TemplateColumn bc = new TemplateColumn();
        bc.HeaderText = strHeader;
        bc.ItemTemplate = new LastFirstNameTemplate();
        grid.Columns.Add(bc);
    }// 这个类实现了一个自定义模板。新控件与容器本身的控件组合创建一个新的模板类,如// 果控件要绑定数据,你可以注册你自己的绑定处理事件(OnDataBinding事件)
    public class LastFirstNameTemplate : ITemplate
    {    // Instantiate the elements of the template in the given
        // container. In this case, a DataGridItem element.    public void InstantiateIn(Control container) 
        {
            container.Controls.Add(new LiteralControl("<b>"));        Label lblLastName = new Label();
            lblLastName.DataBinding += new EventHandler(this.BindLastName);
            container.Controls.Add(lblLastName);        container.Controls.Add(new LiteralControl("</b>, "));        Label lblFirstName = new Label();
            lblFirstName.DataBinding += new EventHandler(this.BindFirstName);
            container.Controls.Add(lblFirstName);
        }    // Handler of the OnDataBinding event for the Label element
        // that renders the lastname column in the template.    private void BindLastName(Object sender, EventArgs e)
        {
                Label l = (Label) sender;
                DataGridItem container = (DataGridItem) l.NamingContainer;
                l.Text = ((DataRowView)container.DataItem)
                    ["lastname"].ToString();
        }    // Handler of the OnDataBinding event for the Label element
        // that renders the firstname column in the template.    private void BindFirstName(Object sender, EventArgs e)
        {
                Label l = (Label) sender;
                DataGridItem container = (DataGridItem) l.NamingContainer;
                l.Text = ((DataRowView)container.DataItem)
                    ["firstname"].ToString();
        }
    }
    这个类可以在asp.net页的<script>部分中定义,也可以在一个单独的类文件中定义.另一种的好的方法是把这定义类的代码放在asp.net页的后台代码源文件中. 在InstantiateIn方法中,简单地创建控件的实例并把它们添加到容器控件中。对于datagrid控件来说,容器控件是一个datagriditem对象。datalist 容器控件是DataListItem对象。容器可以是任何一个实现了INamingContainer接口的类.
    Label lblName = new Label();
    lblName.DataBinding += new EventHandler(this.BindName);
    container.Controls.Add(lblName);
      如果添加到的容器的控件集合中的控件要绑定数据源字段,那么还要为注册您自己的databinding事件处理程序。当databinding事件触发时,从数据源检索数据生成文本并刷新控件的用户界面.如果是自定义服务器控件,databinding事件处理程序需要解析服务器控件以及它所有的子控件中的所有数据绑定表达式。
    void BindName(Object sender, EventArgs e)
    {
      Label l = (Label) sender;
      DataGridItem container;
      container = (DataGridItem) l.NamingContainer;  DataRowView drv;
      drv = ((DataRowView) container.DataItem);
      l.Text = drv["lastname"].ToString();
    }
    databinding事件处理程序完成两项任务。如果编写正确,它应该首先提取并且保持底层数据项;其次,刷新绑定控件的用户界面以反映出数据绑定。
    通过sender参数可以获得相关对象的引用。包含该控件的容器可以由控件本身的namingcontainer属性返回.这时,你就有了设置和使用另一个asp.net表达式Container.DataItem所需要的所有内容。数据项的类型取决于与datagrid关联的数据源。在大多数的实际应用中,它会是DataRowview。剩下的就是访问行中的特定的列并设置控件的绑定属性。
      

  6.   

    给myRadio的ID赋值:myRadio.ID="myID"或者myRadio.Attributes.Add("ID","myID"),后一种方法适用于创建客户端控件的属性;前一种方法则直接使用服务器控件的属性。
      

  7.   

    给myRadio的ID赋值 的方法
        1: 直接在  InstantiateIn 中赋值
                 public void InstantiateIn(Control container)
    {
    RadioButtonList myRadio=new RadioButtonList();
                                         myRadio.id="myid";
                                }
       2:  动态赋值
          在引用ColumnTemplate 时:如下:
             首先给ColumnTemplate 添加字符串变量 str 和一个构造函数
              publci string str=null;
              public ColumnTemplate (string strID)
                          {
                                str=strID;
                           }
                         在InstantiateIn 中调用str
                         public void InstantiateIn(Control container)
    {
    RadioButtonList myRadio=new RadioButtonList();
                                         myRadio.id=strID;
                                }
                            
                          然后是在调用ColumnTemplate 实例化时;
                public  ColumnTemplate cT=new ColumnTemplate(myid) //myid可以动态指定
      

  8.   

    呵呵有点错误:
             把myRadio.id=strID;
               给改成myRadio.id=str;