Please read about lifecycles, roundtrips and viewstates. The problem you run into is you assume the control to be persistent after postback. So when you look into your html you see the TextBox but after you've done some postback it is no longer existent, only the viewstate of it. So in order to get the value you want to access you have to create the control with the SAME ID on each postback and .NET will assign the viewstate to it.
Working example
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security;
using System.Text;
using System.Threading.Tasks;
using Microsoft.VisualBasic;
using System.Data;
partial class _Default : System.Web.UI.Page
{
private DataSet ds;
protected void Button1_Click(object sender, System.EventArgs e)
{
Label lbl;
Label lbltext;
TextBox txt;
foreach (GridViewRow r in gvIndex.Rows)
{
lbl = r.FindControl("lblID");
lbltext = r.FindControl("lblText");
txt = r.FindControl(string.Concat("txt", lbl.Text));
lbltext.Text = txt.Text;
}
}
protected void Page_Load(object sender, System.EventArgs e)
{
if (!this.IsPostBack)
{
DataTable dt = new DataTable();
ds = new DataSet();
dt.Columns.Add("ID", typeof(string));
dt.Rows.Add("1");
dt.Rows.Add("2");
dt.Rows.Add("3");
dt.Rows.Add("4");
dt.AcceptChanges();
ds.Tables.Add(dt);
this.gvIndex.DataSource = ds.Tables[0];
this.gvIndex.DataBind();
}
CreateTextBoxes();
}
public void CreateTextBoxes()
{
Label lbl;
TextBox txt;
foreach (GridViewRow r in gvIndex.Rows)
{
lbl = r.FindControl("lblID");
txt = new TextBox();
txt.ID = string.Concat("txt", lbl.Text);
r.Cells(0).Controls.Add(txt);
}
}
}
and the controls:
<body>
<form id="form1" runat="server">
<div>
<asp:GridView ID="gvIndex" runat="server" AutoGenerateColumns="False">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:Label ID="lblID" runat="server" Text='<%# Eval("ID") %>'></asp:Label>
<asp:Label ID="lblText" runat="server"></asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
<asp:Button ID="Button1" runat="server" Text="Create" />
</div>
</form>
</body>
The controls are added dynamically on each page_load, there are several ways to transport the information of IDs, e.g. in Viewstate or Session object. So in your case after you know the IDs of the controls you added save them in a viewstate or session object (or database), recreate it on next postback and you will find them.