从动态创建的文本框中获取文本,使用ASP.NET。

5
我整个早上都在苦苦思索这个问题,希望能得到一些帮助。实际上,我在使用 .net 4 动态创建文本框控件时遇到了问题。
以下是应用程序的预期流程:
1)用户从下拉菜单中选择一个作为信函模板的 HTML 文档。此 HTML 文档具有格式为 $VARIABLENAME$ 的标记,将被替换为正确的值。
2)程序运行该模板并提取所有格式为 $STRING$ 的字符串,并将它们存储在列表中。
3)对于此列表中的每个条目,程序会生成一个具有基于原始 $VARIABLENAME$ 字段的唯一 ID 的 asp:label 和 asp:textbox。
4)用户输入替换值,然后点击提交。
5)程序将所有 $STRING$ 替换为替换值并输出结果。
一切顺利进行直到需要从文本框中获取值的那一步。我非常确定这是与页面生命周期有关的问题,但由于文本框要在用户从下拉菜单中选择所需模板后才会生成,我不知道如何使它们通过 postback 持久存在,以便可以引用它们。
我是否做错了什么?在 postback 事件发生后,如何访问从下拉事件创建的文本字段?
编辑: 以下是大部分相关代码。
protected void createTextBoxes(List<string> results)
    {
        if (results != null)
        {
            foreach (string result in results)
            {
                string formattedResult = result.Substring(1, result.Length - 2);
                formattedResult = formattedResult.ToLower();
                formattedResult = char.ToUpper(formattedResult[0]) + formattedResult.Substring(1);


                var label = new Label();
                label.ID = formattedResult;
                label.Text = formattedResult + ": ";
                templateFormPlaceholder.Controls.Add(label);

                var textBox = new TextBox();
                textBox.ID = result;
                templateFormPlaceholder.Controls.Add(textBox);
                templateFormPlaceholder.Controls.Add(new LiteralControl("<br />"));

                previewBtn.Visible = true;
            }
        }
    }

protected void templateDD_SelectedIndexChanged(object sender, EventArgs e)
    {
        var templatePath = "";
        if (templateDD.SelectedIndex == 0)
        {
            previewBtn.Visible = false;
        }

        if (templateDD.SelectedIndex == 1)
        {
            templatePath = employeePath;
        }
        else if (templateDD.SelectedIndex == 2)
        {
            templatePath = managerPath;
        }
        List<string> regMatches = FindMatches(templatePath);
        Session["regMatches"] = regMatches;
        createTextBoxes(regMatches);
    }

protected void Page_Init(object sender, EventArgs e)
    {
        if (Session["regMatches"] != null)
        {
            createTextBoxes((List<string>)Session["regMatches"]);
        }
    }

接下来,我想将这些文本框中的值添加到一个字典中。参数是字典的名称。键字段是$STRING$,结果是用户在文本框中输入的内容。

   protected void previewBtn_Click(object sender, EventArgs e)
    {
        List<string> matchResults = (List<string>)Session["regMatches"];
        Dictionary<string, string> parameters = new Dictionary<string, string>();
        foreach (string result in matchResults)
        {
            TextBox tb = (TextBox)templateFormPlaceholder.FindControl(result);
            parameters.Add(result, tb.Text);
        }

        var template = ReplaceKeys(parameters);
        outputLBL.Text = template;

这是 .aspx 代码。

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="offerLetter.aspx.cs"     Inherits="templateRegexTesting.offerLetter" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
    <p>
        Which template would you like to use?
    </p>
    <asp:DropDownList ID="templateDD" runat="server" OnSelectedIndexChanged="templateDD_SelectedIndexChanged"
        AutoPostBack="true">
        <asp:ListItem></asp:ListItem>
        <asp:ListItem Value="1">Employee</asp:ListItem>
        <asp:ListItem Value="2">Manager</asp:ListItem>
    </asp:DropDownList>
    <br />
    <asp:PlaceHolder ID="templateFormPlaceholder" runat="server" />
    <div>
        <asp:Button ID="previewBtn" runat="server" Text="Preview" Visible="false" OnClick="previewBtn_Click" />
    </div>
    <div>
        <asp:Label ID="outputLBL" runat="server"></asp:Label>
    </div>
    <br />
</div>
</form>
</body>
</html>

编辑:当我解决问题时,我将这条信息写在了评论区,但我认为我应该将它移到问题区,以便更加显眼:

我觉得我应该更新一下这个问题。我有点傻,但我设法让它工作了。基本上,我给控件分配了一个等于替换标记的ID(例如ID="$FIRSTNAME$")。我甚至没有意识到$会导致任何问题。当我只是把格式改为ID="Firstname"时,它完美地工作。感谢你们所有人的帮助!


特别是在创建控件时。 - banging
你尝试过什么?(http://mattgemmell.com/2008/12/08/what-have-you-tried/) - Kash
我觉得我应该更新一下。我觉得自己有点傻,但我成功地让它工作了。基本上,我将控件分配一个等于替换标记的ID(例如,ID="$FIRSTNAME$") 。我甚至没有想到$会引起任何问题。当我只是更改为格式ID="Firstname"时,它就完美地工作了。感谢你们的所有帮助! - mElling
3个回答

7
您说得对,这与页面生命周期有关。为了在视图状态绑定阶段之前存在,必须在Page_Init阶段重新创建动态创建的控件。这意味着您需要以某种方式(也许使用Session)存储上一个处理过程中创建的textboxes数量以重新创建它们。请记住使用相同的ID并将它们添加到控件树中(重复者或其他您正在使用的控件)。

更新

让我给你一个建议: 1.声明一个类型为List<TextBox>的类属性(我们将其称为CreatedTextBoxes

  1. 声明一个方法,接收需要创建文本框的任何内容。此方法不得在其范围之外读取任何内容。它将简单地接收一些args,创建文本框并将其添加到另一个控件(例如Repeater)。将每个创建的文本框添加到CreatedTextBoxes中。

  2. 在下拉列表更改事件中,读取选项,将其保存到Session中,并调用此方法

  3. Page_Init中,验证Session中的对象。如果它为空或没有值,请不要执行任何操作。如果有一个值,请调用相同的方法,传递相同的args

  4. 当您需要从动态创建的文本框中检索它时,请使用CreatedTextBoxes而不是FindControls()

那么在 Page_Init 阶段,我是不是必须再次运行创建基于下拉选择的文本框方法?把它放在 Page_Init 方法中会导致页面在第一次访问页面时(在进行下拉选择之前)尝试创建文本框吗? - mElling
是的,没错,这就是为什么你要找出一些"流程控制"。我会在问题中提供一个建议。 - Andre Calil
不幸的是,我仍然无法找到文本框控件来获取文本。我又编辑了我的初始帖子,将所有似乎相关的代码都包含进去了。 - mElling
此外,从下拉列表中选择超过一次将导致其出现故障,因为下拉列表和page_init方法都会尝试创建具有相同ID的控件。 - mElling
如果我设置一个断点并步进到那个点,TextBox tb将为null。此外,以下是它抛出的错误信息:System.NullReferenceException: Object reference not set to an instance of an object。源错误:Line 125: { Line 126: TextBox tb = (TextBox)form1.FindControl(result); Line 127: parameters.Add(result, tb.Text); Line 128: } Line 129: - mElling
显示剩余17条评论

1
创建动态文本框并将其添加到 ASP 面板中,以便您可以轻松访问它。
这是 ASP.NET 的设计元素。
<div class="form-group">
<asp:Panel ID="panel" runat="server" CssClass="form-group">

</asp:Panel>
</div>

生成动态文本框的C#代码

 protected void create_dynamic_text(object sender, EventArgs e)
{
    int num = 5; // you can give the number here
    for (int i = 0; i < num;i++ )
    {
        TextBox tb = new TextBox();
        tb.ID = "txt_box_name" + i.ToString();
        tb.CssClass = "add classes if you need";
        tb.Width = 400; //Manage width and height 
        panel.Controls.Add(tb); //panel is my ASP.Panel object. Look above for the design code of ASP panel
    }
}

C#代码获取数值

 protected void reade_values(object sender, EventArgs e)
{
   int num=5; // your count goes here
    TextBox tb = new TextBox();
        for (int i = 0; i < num; i++)
        {
           tb=(TextBox)panel.FindControl("txt_box_name"+i.ToString());
           string value = tb.Text; //You have the data now
        }
    }
}

1
您将TextBox控件添加到templateFormPlaceholder.Controls中,但使用form1.FindControl来查找它们。FindControl方法仅在指定的容器直接包含控件时才能找到该控件 - 来自http://msdn.microsoft.com/en-us/library/486wc64h.aspx。请尝试调用templateFormPlaceholder.FindControl

很好的发现,但不幸的是将其更改为form1只是最后一招孤注一掷的尝试。即使将其更改回TextBox tb =(TextBox)templateFormPlaceholder.FindControl(result); parameters.Add(result,tb.Text);也会导致nullreferenceexception。我会更新我的原始帖子以反映这一点。 - mElling

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接