无法动态创建文本框并在同一回发中检索值

时间:2013-12-04 23:32:46

标签: c# asp.net textbox

我正在尝试根据用户的请求动态创建文本框控件。

问题是我无法在同一回发中创建动态文本框并进行检索 用户输入的号码,并使用该号码创建其他文本框。

似乎我总是背后一个回发。

这是我示例中的整个代码,我在HTML页面中没有其他代码。

请帮助我解决问题,以便我可以创建用户在请求时请求的文本框数量。

public partial class _Default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {

        form1.InnerText = "how many TextBoxes would you like to add?";
        form1.InnerHtml += "<br />";

        TextBox tb = new TextBox();
        tb.ID = "TextBox1";
        tb.Attributes.Add("type", "number");
        tb.Attributes.Add("runat", "server");
        tb.Attributes.Add("min", "1");
        tb.Attributes.Add("max", "5");                
        tb.AutoPostBack = true;
        tb.TextChanged += new EventHandler(textBox_TextChanged);
        form1.Controls.Add(tb);

        if (tb.Text != "")
        {            
            for (int i = 0; i < Convert.ToInt16(tb.Text); i++)
            {
                TextBox tb1 = new TextBox();
                tb1.ID = "newTB" + i.ToString();
                form1.Controls.Add(tb1);
            }     
        }                    
    }

    protected void textBox_TextChanged(object sender, EventArgs e)
    {
    }
}

我尝试编写最短最简单的代码,因为我只想弄清楚我的问题背后的原理,我找不到类似于我的问题。

2 个答案:

答案 0 :(得分:0)

好的,所以你的代码不遵循标准的asp.net编码实践。以下是您尝试实现的一个简单的工作示例:

表单代码

<form id="form1" runat="server">
    <div>
        <asp:Label ID="Label1" runat="server" Text="Label">How many textboxes would you like to create?</asp:Label>
        <asp:TextBox ID="TextBox1" runat="server" AutoPostBack="True" 
            ontextchanged="TextBox1_TextChanged"></asp:TextBox>
        <asp:RangeValidator ID="RangeValidator1" runat="server" 
            ControlToValidate="TextBox1" ErrorMessage="Invalid Number" MaximumValue="5" 
            MinimumValue="1"></asp:RangeValidator>
    </div>
</form>

代码背后

protected void Page_Load(object sender, EventArgs e)
    {

    }
    protected void TextBox1_TextChanged(object sender, EventArgs e)
    {
        if (TextBox1.Text != "")
        {
            for (int i = 0; i < Convert.ToInt16(TextBox1.Text); i++)
            {
                TextBox tb1 = new TextBox();
                tb1.ID = "newTB" + i.ToString();
                form1.Controls.Add(tb1);
            }
        }   
    }

我真的建议您阅读asp.net页面lifecycle并阅读一些基本示例来了解基本原则。这个tutorial是一个很好的起点。

编辑 - 修改:下面是你的问题的另一个刺,再次需要一点爱和重构(我相信可能有更好的方法来做到这一点!)但它的确有效。在我的测试表单中,我有一个提交按钮,然后创建的文本框然后在回发之间“保留”它们的值(但它们实际上是从请求中重新创建的)。

代码背后

protected void Page_Load(object sender, EventArgs e)
{
    if (IsPostBack)
    {
        foreach (string key in Request.Form)
        {
            if (key.StartsWith("newTB"))
            {
                TextBox tb1 = new TextBox();
                tb1.ID = key;
                tb1.Text = Request.Form[key];
                form1.Controls.Add(tb1);
            }
        }
    }
}

protected void Page_Init(object sender, EventArgs e)
{
    Label label1 = new Label()
        {
            ID = "label1",
            Text = "How many textboxes would you like to create?"
        };

    form1.Controls.Add(label1);

    TextBox textBox1 = new TextBox()
        {
            ID = "TextBox1",
            AutoPostBack = true,
            CausesValidation = true
        };

    textBox1.TextChanged += new EventHandler(TextBox1_TextChanged);

    form1.Controls.Add(textBox1);

    RangeValidator rangeValidator = new RangeValidator()
        {
            ID="RangeValidator1",
            ControlToValidate = "TextBox1",
            MaximumValue = "5",
            ErrorMessage = "Out of range!",
            MinimumValue = "1"
        };

    form1.Controls.Add(rangeValidator);
}

protected void TextBox1_TextChanged(object sender, EventArgs e)
{
    TextBox textBox = form1.FindControl("TextBox1") as TextBox;

    if (Page.IsValid && textBox.Text != "")
    {
        RemoveOldControls();

        for (int i = 0; i < Convert.ToInt16(textBox.Text); i++)
        {
            TextBox tb1 = new TextBox();
            tb1.ID = "newTB" + i.ToString();
            form1.Controls.Add(tb1);
        }
    }
}

//Recursive method to remove all "newTB" textboxes
private void RemoveOldControls()
{
    for (int i = 0; i < form1.Controls.Count; i++)
    {
        if (!string.IsNullOrEmpty(form1.Controls[i].ID) && form1.Controls[i].ID.StartsWith("newTB"))
        {
            TextBox newTextBox = form1.Controls[i] as TextBox;

            if (newTextBox != null)
                form1.Controls.Remove(newTextBox);

            RemoveOldControls();
            break;
        }
    }
}

答案 1 :(得分:0)

希望这可以帮到你。

public partial class SomeClass
{
    private TextBox _textBox;
    protected void Page_Init(object sender, EventArgs e)
    {
        _textBox = new TextBox { EnableViewState = true };
        _textBox.TextChanged += (o, args) =>
                                    {

                                    };
        Wrapper.Controls.Add(_textBox);
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        if(!IsPostBack)
        {
            _textBox.Text = "Initial Text";
        }
        else
        {
            // Loaded from viewstate, yay.
        }
    }
}

<asp:Content ID="Content3" ContentPlaceHolderID="ContentPlaceHolderMainContent" runat="server">
    <asp:Panel runat="server" ID="Wrapper"/>
    <asp:Button runat="server" Text="PostBack!"/>
</asp:Content>

您应该始终在Page_Init中添加动态控件。

以下是我测试的内容:

  • 代码(在调试中)在Page_Init,Page_Load
  • 中断
  • “初始文本”已设置为Page_Load中的文本框。
  • 我将文字更改为“Initial Text123”
  • 我点击导致PostBack的按钮
  • 代码(在调试中)在Page_init,Page_Load,TextChanged处理程序中断。
  • 我可以看到,只要我在Page_Load中,文本框就包含文本“Initial Text123”,因为它已经从ViewState重新加载了它的值。