title: ASP.NET - Problem with GridView with Dynamic Columns
body: <p>I have a GridView that includes BoundField and TemplateField elements. Some of the TemplateField elements are dynamically generated. For the sake of reference, here is the GridView that I am using</p>
  
  <pre><code>  &lt;asp:GridView ID="myGridView" runat="server" AutoGenerateColumns="False" 
        DataKeyNames="ID" ShowFooter="True" EnableModelValidation="True"
        OnLoad="myGridView_Load" OnRowCommand="myGridView_RowCommand"
        OnRowEditing="myGridView_RowEditing" OnRowDeleting="myGridView_RowDeleting"  
        OnRowCancelingEdit="myGridView_RowCancelingEdit" 
        OnRowUpdating="myGridView_RowUpdating"&gt;
        &lt;Columns&gt;
          &lt;asp:BoundField DataField="Number" Visible="true" HeaderText="Test" /&gt;
          &lt;asp:TemplateField HeaderText="Number"&gt;
            &lt;EditItemTemplate&gt;
              &lt;asp:TextBox ID="tb1" runat="server" Text='&lt;%# Bind("Number") %&gt;' /&gt;
            &lt;/EditItemTemplate&gt;
            &lt;ItemTemplate&gt;
              &lt;asp:Label ID="lb1" runat="server" Text='&lt;%# Bind("Number") %&gt;' /&gt;
            &lt;/ItemTemplate&gt;
            &lt;FooterTemplate&gt;
              &lt;asp:TextBox ID="ftb" runat="server" Text="[x]" /&gt;
            &lt;/FooterTemplate&gt;
          &lt;/asp:TemplateField&gt;
  
          &lt;%-- Dynamically Generated Columns Will Be Inserted Here --%&gt;
  
          &lt;asp:TemplateField HeaderText="Actions"&gt;
            &lt;EditItemTemplate&gt;
              &lt;asp:LinkButton ID="ulb" runat="server" Text="update" CommandName="Update" /&gt;
              &lt;asp:LinkButton ID="clb" runat="server" Text="cancel" CommandName="Cancel" /&gt;
            &lt;/EditItemTemplate&gt;
            &lt;FooterTemplate&gt;
              &lt;asp:LinkButton ID="slb" runat="server" Text="insert"  
                OnClick="saveLinkButton_Click" /&gt;
            &lt;/FooterTemplate&gt;
            &lt;ItemTemplate&gt;
              &lt;asp:LinkButton ID="elb" runat="server" Text="edit" CommandName="Edit" /&gt;
              &lt;asp:LinkButton ID="dlb" runat="server" Text="delete" CommandName="Delete" /&gt;
            &lt;/ItemTemplate&gt;
          &lt;/asp:TemplateField
     &lt;/Columns&gt;                                                                                                                    
        &lt;EmptyDataTemplate&gt;
          &lt;table border="0" cellpadding="0" cellspacing="0"&gt;
            &lt;tr&gt;&lt;td&gt;Number&lt;/td&gt;&lt;/tr&gt;
            &lt;tr&gt;
              &lt;td&gt;&lt;asp:TextBox ID="ntb" runat="server" /&gt;&lt;/td&gt;
              &lt;td&gt;&lt;asp:LinkButton ID="slb2" runat="server" Text="save" OnClick="saveLinkButton_Click" /&gt;&lt;/td&gt;
            &lt;/tr&gt;
          &lt;/table&gt;
        &lt;/EmptyDataTemplate&gt;                                                                                
      &lt;/asp:GridView&gt;
  </code></pre>
  
  <p>When the GridView initially loads, everything is loaded properly. However, anytime I perform a command (edit, insert, delete), all of the data goes away. Oddly, the BoundField values still appear correctly. However, any TemplateField does not seem to get rendered. The code that I am using to work with this GridView is here:</p>
  
  <pre><code>public partial class GridView : System.Web.UI.Page
  {
      private List&lt;string&gt; dynamicColumnNames = new List&lt;string&gt;();
  
      protected void Page_Load(object sender, EventArgs e)
      {
          LoadPageData();
      }
  
      protected void saveLinkButton_Click(object sender, EventArgs e)
      {
      }
  
      protected void myGridView_Load(object sender, EventArgs e)
      {
          if (Page.IsPostBack == false)
          {
              BindGridData();
          }
      }
  
      protected void myGridView_RowCommand(object sender, GridViewCommandEventArgs e)
      { }
  
      protected void myGridView_RowEditing(object sender, GridViewEditEventArgs e)
      {
          myGridView.EditIndex = e.NewEditIndex;
          BindGridData();
      }
  
      protected void myGridView_RowDeleting(object sender, GridViewDeleteEventArgs e)
      {
          LoadPageData();
          BindGridData();
      }
  
      protected void myGridView_RowCancelingEdit(object sender, EventArgs e)
      {
          myGridView.EditIndex = -1;
          BindGridData();
      }
  
      protected void myGridView_RowUpdating(object sender, GridViewUpdateEventArgs e)
      {
          myGridView.EditIndex = -1;
          LoadPageData();
          BindGridData();
      }
  
      private void BindGridData()
      {
          // Create a temporary data source
          DataTable tempData = new DataTable();
          tempData.Columns.Add("ID");
          tempData.Columns.Add("Number");           
  
          // Dynamically add template columns
          foreach (string columnName in dynamicColumnNames)
          {
              tempData.Columns.Add(columnName);
  
              TemplateField templateField = new TemplateField();
              templateField.HeaderTemplate = new MyTemplateField(ListItemType.Header, columnName);
              templateField.ItemTemplate = new MyTemplateField(ListItemType.Item, columnName);
              templateField.EditItemTemplate = new MyTemplateField(ListItemType.EditItem, columnName);
              templateField.FooterTemplate = new MyTemplateField(ListItemType.Footer, columnName);
              myGridView.Columns.Insert(2, templateField);
          }
  
          // Add some phony data
          Random random = new Random(DateTime.Now.Millisecond);
          for (int i = 0; i &lt; 10; i++)
          {
              DataRow tempRow = tempData.NewRow();
              tempRow["Number"] = (i + 1);
  
              foreach (string column in dynamicColumnNames)
                  tempRow[column] = random.NextDouble();
              tempData.Rows.Add(tempRow);
          }
  
          // Bind the data to the grid
          myGridView.DataSource = tempData;
          myGridView.DataBind();
      }
  
      private void LoadPageData()
      {
          dynamicColumnNames.Add("USA");
          dynamicColumnNames.Add("Japan");
          dynamicColumnNames.Add("Mexico");
      }
  }
  
  internal class MyTemplateField : ITemplate
  {
      // The type of the list item
      private ListItemType listItemType;
  
      // The value to use during instantiation
      private string value1 = string.Empty;
  
      public MyTemplateField(ListItemType listItemType, string value1)
      {
          this.listItemType = listItemType;
          this.value1 = value1;
      }
  
      public void InstantiateIn(Control container)
      {
          if (listItemType == ListItemType.Item)
          {
              TextBox textBox = new TextBox();
              textBox.ReadOnly = true;
              textBox.DataBinding += new EventHandler(textBox_DataBinding);
              container.Controls.Add(textBox);
          }
          else if (listItemType == ListItemType.EditItem)
          {
              TextBox textBox = new TextBox();
              textBox.DataBinding += new EventHandler(textBox_DataBinding);
              container.Controls.Add(textBox);
          }
          else if (listItemType == ListItemType.Header)
          {
              Literal literal = new Literal();
              literal.Text = value1;
              container.Controls.Add(literal);
          }
          else if (listItemType == ListItemType.Footer)
          {
              TextBox textBox = new TextBox();
              container.Controls.Add(textBox);
          }
      }
  
      private void textBox_DataBinding(object sender, EventArgs e)
      {
          TextBox textBox = (TextBox)(sender);
          GridViewRow row = (GridViewRow)(textBox.NamingContainer);
  
          textBox.Text = DataBinder.Eval(row.DataItem, value1).ToString();
      }
  }
  </code></pre>
  
  <p>How do I use commands in a GridView with Dynamically added columns? What is wrong with my code?</p>
  
  <p>Thank you!</p>