【问题标题】:ASP.net dynamic grid of textboxesASP.net 动态文本框网格
【发布时间】:2012-07-02 23:49:53
【问题描述】:

我有 2 个字符串列表,我想动态创建一个文本框网格:

List<string> X = {"A", "B", "C"};
List<string> Y = {"1", "2", "3", "4"};

          A     B     C
     1   TBX   TBX   TBX
     2   TBX   TBX   TBX
     3   TBX   TBX   TBX
     4   TBX   TBX   TBX

     [Button]

当我在文本框中输入数据并单击按钮时,我希望能够遍历这些文本框并确定与每个文本框关联的“X”和“Y”坐标。

我大概可以弄清楚如何动态创建这个文本框网格,但我想我在发布数据时会遇到问题。回发后如何从动态创建的文本框中获取值?

我在进行迭代和实际逻辑时不会有任何问题,但我不知道如何将数据放入容器中以便进行迭代。在阅读发布的数据时,我是否必须再次动态创建文本框?那是什么样子的?

【问题讨论】:

  • 网络表单。这是一种用于输入管状数据的数据输入技巧。会有一些 javascript 的东西进行一些解析。

标签: c# asp.net c#-4.0 webforms


【解决方案1】:

这是另一种方法。您可以在 asp.net 页面中有一个占位符。在后面的代码中动态创建一个带有动态文本框的表格并将其插入到占位符中。在这种情况下,您可以控制每个文本框的 ID。在回发时输入到文本框中的值将被保留(因为 ID 是确定的,您也可以进行 javascript 操作)

这是aspx

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

<!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>
        <asp:PlaceHolder ID="PHDynamicTable" runat="server"></asp:PlaceHolder>
        <asp:Button runat="server" ID="btnSubmit" Text="Submit" 
            onclick="btnSubmit_Click" />
    </div>
    </form>
</body>
</html>

背后的代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

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

        }

        protected override void OnPreInit(EventArgs e)
        {
            base.OnPreInit(e);
            CreateTextBoxesInTable();
        }

        private void CreateTextBoxesInTable()
        {
            PHDynamicTable.Controls.Clear();

            List<string> X = new List<string>() { "A", "B", "C" };
            List<string> Y = new List<string>() { "1", "2", "3", "4" };

            Table table = new Table();
            table.ID = "dynamicTable";

            TableRow tr;
            foreach (string y in Y)
            {
                tr = new TableRow();

                foreach (string x in X)
                { 
                    TableCell tc = new TableCell();

                    TextBox textBox = new TextBox();
                    textBox.ID = "txt_" + x + y;
                    tc.Controls.Add(textBox);

                    tr.Cells.Add(tc);
                }

                table.Rows.Add(tr);
            }

            PHDynamicTable.Controls.Add(table);
        }

        protected void btnSubmit_Click(object sender, EventArgs e)
        {
            if (PHDynamicTable.Controls.Count > 0)
            {
                Table dynamicTable = (Table)PHDynamicTable.FindControl("dynamicTable");
                if (dynamicTable != null)
                {
                    foreach (TableRow tr in dynamicTable.Rows)
                    {
                        foreach (TableCell tc in tr.Cells)
                        {
                            TextBox textBox = (TextBox)tc.Controls[0];
                            string text = textBox.Text;
                            //Do whatever you want with the control
                        }
                    }
                }
            }
        }
    }
}

几个屏幕截图

输入数据的屏幕

在回发(提交)时

提交后

【讨论】:

  • 谢谢。我基本上是从这条路开始的,但你这样做的方式更干净。
  • 我认为这看起来很适合我正在做的事情,但如果我从 OnPreInit 调用 CreateTextBoxesInTable,PHDynamicTable 就“什么都不是”。如果我在“If Not IsPostback”子句中从 Page_Load 调用它,则在单击更新按钮后该表会消失。我不得不深入研究页面加载事件的顺序。可能没有坏事。
  • @user910683 也许你应该看到这个;但再次仅供参考:msdn.microsoft.com/en-us/library/ms178472.aspx#lifecycle_events
  • 谢谢普拉桑斯。我确实看过它,它帮助我确定我需要的是 OnPreLoad。我使用的是 VB.NET 而不是 C#(不是选择!)所以我的代码与给出的代码不完全相同。虽然这是直接翻译,但我的理解是生命周期事件的顺序不受所用语言的影响。
【解决方案2】:

除了可用性问题,我将假设您使用的是 ASP.NET Webforms 而不是 ASP.NET MVC。在网络表单中,这变成了一场噩梦。您当然可以嵌套两个控件。一个控件的数据源成为第一个列表,第二个数据源是第二个列表。然后在辅助中继器模板中放置您的 asp:textbox。但是,即使显式设置,此处的 ID 实际上也会是生成的值,因为转发器是 ASP.nET Webforms 中已知的命名容器;这意味着 ID 的值将在运行时更改。

在回发时,您可以遍历父转发器的控制树以找到子转发器。然后在子中继器中,您可以遍历该中继器的控件以找到您的文本框。类似:

<asp:Repeater>
    <itemtemplate>
        <asp:repeater>
            <itemtemplate>
                <asp:textbox />
            </itemtemplate>
        </asp:repeater>   
    </itemtemplate>
</asp:repeater>

然后在后面的代码中,在 Post Back [伪代码]

foreach(Control c in myTopRepeater.Controls){
    if(c == RepeaterControl) //is of type repeater. again, pseudo code
    {
         foreach(Control subC in c)
         {
             if(subC == textBox)
             {
                 //Compare generated name, etc to my Lists

             }
         }
    }
}

阅读命名容器可能会有所帮助。您可以获得可预测的命名设置,但它不是 100% 直观的。 http://www.4guysfromrolla.com/articles/031710-1.aspx

祝你好运!

【讨论】:

  • 是的,我建议在 Web 表单中这样做。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-26
  • 2013-07-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多