【问题标题】:How to add TemplateField created in .aspx markup to GridView column in code behind?如何将 .aspx 标记中创建的 TemplateField 添加到代码后面的 GridView 列?
【发布时间】:2026-02-08 10:20:21
【问题描述】:

基本上,我想要一个按钮,用于向我的 GridView 添加一个带有我的控件(即 TextBox、DropDownList)的新列。

看起来已经很简单了:

protected void btn_AddColumn_Click(object sender, EventArgs e)
{
    TemplateField MyTemplateField = new TemplateField();
    gv_SupplierPrices.Columns.Add(MyTemplateField);
}

假设我想添加这个标记:

<asp:TemplateField>
    <ItemTemplate>
       <table style="width:100%;">
          <tr>
             <td><asp:TextBox ID="tbox_ItemPrice" runat="server"></asp:TextBox></td>
          </tr>
       </table>
     </ItemTemplate>
</asp:TemplateField>

这就是问题所在。如何使用我在 .aspx 页面上的标记中创建的 TemplateField 并将其添加到我在代码后面的新列中?我不知道也不想在后面的代码上创建我的 TemplateField,因为我将无法创建精致或花哨的标记。它们看起来就像彼此相邻的控件。太丑了。

附:如果有人对我实际制作的内容感到好奇,我基本上是将我的 GridView 变成了类似 Excel 的网格表。新列代表一个供应商,每一行代表供应商正在销售的一个项目。他们想要这样,因为在他们填满的时候更容易并排比较价格。


更新:我已经想通了。我可以简单地从代码隐藏中调用我的 GridView 的列,该列代表我在标记中创建的 TemplateField,然后添加它。

<asp:GridView ID="gv_SupplierTable" runat="server" AutoGenerateColumns="False" 
                        DataKeyNames="Id" DataSourceID="TestTable_DS">
                        <Columns>
                            <asp:BoundField DataField="Id" HeaderText="Id" InsertVisible="False" 
                                ReadOnly="True" SortExpression="Id" />
                            <asp:BoundField DataField="AccountType" HeaderText="AccountType" 
                                SortExpression="AccountType" />
                            <asp:TemplateField AccessibleHeaderText="MyTemplateFieldCreated in Markup">
                                <ItemTemplate>
                                    <table style="width:100%;">
                                        <tr>
                                            <td><asp:TextBox ID="tbox_ItemPrice" runat="server"></asp:TextBox></td>
                                        </tr>
                                    </table>
                                </ItemTemplate>
                            </asp:TemplateField>
                        </Columns>
                    </asp:GridView>

然后在代码隐藏中,我可以访问代表在标记中创建的 TemplateField 的列,并在单击按钮时再次添加它,就像一个新副本:

    protected void btn_AddColumn_Click(object sender, EventArgs e)
    {
    DataControlField newColumn = this.gv_SupplierTable.Columns[2]; 
                                 //this column at index #2 from my GridView represents                  
                                 the TemplateField created in markup since the columns  
                                 at index #0 and index #1 are DataBound.
    gv_SupplierTable.Columns.Add(newColumn);
    }

【问题讨论】:

    标签: asp.net gridview controls templatefield


    【解决方案1】:

    您可以切换每列的可见性。

    gv_SupplierPrices.Columns[10].Visible = true;
    

    【讨论】:

    • 不管你信不信,这是更简单的方法。预先创建您需要的所有列和行,并在设计时隐藏它们。然后根据需要从您的代码隐藏中释放它们,我建议在 databound() 事件中
    【解决方案2】:

    在您的位置上,我会考虑硬着头皮研究以编程方式创建模板化字段。这会很麻烦,但是一旦你完成了,你就完成了。当然,您希望将它们抽象为辅助类或单独的控件。

    【讨论】:

      【解决方案3】:

      这里有几个关于动态添加列到您的GridView 的示例:

      protected void Page_Init(object sender, EventArgs e)
      {
          btnAddColumn.Click += new EventHandler(btnAddColumn_Click);
      
          BoundField temp = new BoundField();
          temp.DataField = "Source";
          temp.HeaderText = "Source";
          temp.SortExpression = "Source";
      
          gv.Columns.Add(temp);
      }
      
      void btnAddColumn_Click(object sender, EventArgs e)
      {
          TemplateField temp = new TemplateField();
          temp.HeaderText = txtNewColumn.Text;
      
          txtNewColumn.Text = string.Empty;
      
          gv.Columns.Add(temp);
      }
      

      ASPX:

      <div>
          <asp:TextBox ID="txtNewColumn" runat="server" />
          <asp:Button ID="btnAddColumn" runat="server" Text="Add Column" />
      </div>
      <asp:GridView ID="gv"
          runat="server"
          AutoGenerateColumns="False"
          DataSourceID="dsExceptions">
          <Columns>
              <asp:BoundField DataField="Message" HeaderText="Message" />
          </Columns>
      </asp:GridView>
      
      <asp:ObjectDataSource ID="dsExceptions"
          runat="server" 
          SelectMethod="GetExceptions"
          TypeName="WebApplication.Data.MyDataContext" EnablePaging="True" 
          SelectCountMethod="GetExceptionCount" >
          <SelectParameters>
              <asp:Parameter Name="maximumRows" Type="Int32" />
              <asp:Parameter Name="startPageIndex" Type="Int32" />
              <asp:Parameter Name="startRowIndex" Type="Int32" />
          </SelectParameters>
      </asp:ObjectDataSource>
      

      我的 ObjectDataSource 只是获得了我创建的 Exceptions 的集合,因此您可以忽略这部分代码。

      因此,我通过Page_Init 处理程序中的代码添加一列,并添加一列,其中标题文本设置为txtNewColumn 中的文本。但是,关于这一点的一件事是,如果您刷新页面,它将丢失您使用页面上的按钮添加的列。您需要在按钮单击事件处理程序中添加一些代码来存储新列,因此它们在重新加载时始终位于 GridView 中。由于听起来这些列代表供应商,因此您可能只想添加一个表单以供某人将供应商添加到您的系统中。供应商被保存在某处的数据库/数据存储中,在Page_Init 中,您从该数据存储中获取所有供应商并遍历它们,为供应商创建模板字段。应该是这样的:

      // I am just creating a list here, you would pull the vendor names in from the 
      // datastore here instead.
      var vendors = new List<string> { "Vendor A", "Vendor B", "Vendor C" };
      foreach (var vendor in vendors)
      {
          TemplateField temp = new TemplateField();
          temp.HeaderText = vendor;
          gv.Columns.Add(temp);
      }
      

      【讨论】:

      • 是的。一列代表供应商/供应商,第一列(最左边)是唯一绑定字段。第一列的每个单元格代表一个项目,用户必须指定每个项目的供应商价格。即戴尔台式机:供应商 A - 499 美元/台。供应商 B - 479 美元/个。供应商 C - 510 美元/个。我需要能够添加尽可能多的供应商(作为列)。我很感激你的回复。但它仍然没有让我知道如何获取我在标记中创建的 TemplateField 并将其从代码隐藏添加到我的列中。我不知道也不想以编程方式创建 ASP 控件。
      • 我展示了如何动态创建列,但不确定您还需要什么。做你需要做的事,这将是最简单的方法。
      • 您展示了如何动态添加列。我已经在我的帖子中用两行代码做到了这一点。我正在寻找的是使用我在 MARKUP 中创建的 TemplateField,而不是 CODEBEHIND,并将其作为新列动态添加到 GridView。您发布的内容仍然是在代码隐藏中创建 DataControlFields,而不是标记。
      • 抱歉,我读到它就像您想添加一列,将其放入带有该标记的列中。不过,很高兴您找到了解决方案。实际上是聪明的方式!