【问题标题】:Can't get values out of dynamically added textbox无法从动态添加的文本框中获取值
【发布时间】:2013-07-12 11:57:14
【问题描述】:

尽我所能,我无法从动态添加的文本框中获取值。我尝试在所有包含控件中启用 ViewState 以及在 Page_Init 事件中将文本框值添加到 ViewState,但 Text 属性始终为空。这是我的页面背后的代码...

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using O2S.Components.PDF4NET;
using O2S.Components.PDF4NET.Graphics;
using O2S.Components.PDF4NET.Graphics.Fonts;
using O2S.Components.PDF4NET.Graphics.Shadings;
using O2S.Components.PDF4NET.Graphics.Shapes;

namespace PDFFormToGrid
{
    public partial class Form : System.Web.UI.Page
    {
        private static double leftMargin = 15;
        private static double rightMargin = 15;
        private static double topMargin = 20;
        private static double minBottomMargin = 20;
        private static double rowHeight = 30;
        private static double headerHeight = 30;
        private static double firstPageTopOffset = 50;
        private static double[] columnsWidth = { 120, 120, 120, 120 };
        private static string[] columnsHeader = { "Name", "Phone Number", "Address", "Company" };
        private static List<Control> panels = new List<Control>();
        private static List<TextBox> fields = new List<TextBox>();

        protected void Page_Load(object sender, EventArgs e)
        {
            if (!Page.IsPostBack)
            {
                panels.Clear();
            }
        }

        protected void btnSubmit_Click(object sender, EventArgs e)
        {
            PDFDocument form = CreatePDF(this);

            Response.ContentType = "application/x-msdownload";
            Response.AddHeader("content-disposition", "attachment;filename=form.pdf");
            form.Save(Response.OutputStream);
            Response.Flush();
            Response.End();
        }

        private static PDFDocument CreatePDF(Form form)
        {
            // Create the PDF document
            PDFDocument doc = new PDFDocument();

            // Create the graphics objects
            PDFFont titleFont = new PDFFont(PDFFontFace.Helvetica, 35);
            PDFBrush purpleTitleBrush = new PDFBrush(new PDFRgbColor(19, 19,105));

            formatDoc(doc);

            // Create first page of report
            PDFPage page = doc.AddPage();

            formatPage(page, titleFont, purpleTitleBrush);

            DrawReportRows(doc, page, panels);

            return doc;
        }


        private static void formatDoc(PDFDocument doc)
        {
            doc.SerialNumber = "Serial Number Goes Here";
            doc.PageOrientation = PDFPageOrientation.Landscape;
        }

        private static void formatPage(PDFPage page, PDFFont font, PDFBrush brush)
        {
            // Draw title of report
            page.Canvas.DrawText("Applicant", font, null, brush, page.Width / 2, 
                15, 0, PDFTextAlign.TopCenter);

            // Draw report header
            DrawReportHeader(page, firstPageTopOffset);
        }

        private static void DrawReportHeader(PDFPage page, double headerTopOffset)
        {
            // Create the graphics objects
            PDFFont headerFont = new PDFFont(PDFFontFace.Helvetica, 12);
            headerFont.Bold = true;
            PDFPen borderColor = new PDFPen(new PDFRgbColor(), 4);
            PDFBrush textColor = new PDFBrush(new PDFRgbColor());
            PDFBrush headerFill = new PDFBrush(new PDFRgbColor(192, 192, 193));

            // Draw the header
            page.Canvas.DrawRectangle(borderColor, headerFill, leftMargin, headerTopOffset,
                page.Width - leftMargin - rightMargin, headerHeight);

            double xOffset = leftMargin;
            // Draw the column separators
            for (int i = 0; i < columnsWidth.Length - 1; i++)
            {
                xOffset = xOffset + columnsWidth[i];
                page.Canvas.DrawLine(borderColor, xOffset, headerTopOffset,
                    xOffset, headerTopOffset + headerHeight);
            }

            xOffset = leftMargin;
            // Draw the columns header
            for (int i = 0; i < columnsWidth.Length; i++)
            {
                page.Canvas.DrawText(columnsHeader[i], headerFont, null, textColor,
                    xOffset + columnsWidth[i] / 2, headerTopOffset + headerHeight / 2, 0, PDFTextAlign.MiddleCenter);
                xOffset = xOffset + columnsWidth[i];
                xOffset = xOffset + columnsWidth[i];
            }

        }

        private static void DrawReportRows(PDFDocument doc, PDFPage page, List<Control> panels)
        {
            // Get number of forms - there's one more than count because of the initial form
            int numForms = panels.Count;

            double rowOffset = firstPageTopOffset + headerHeight;
            for (int i = 0; i < numForms; i++)
            {
                if (rowOffset + rowHeight > page.Height - minBottomMargin)
                { // not enough space to draw a new row, then create a new page, 
                    // draw the header, then draw the rows.
                    page = doc.AddPage();
                    DrawReportHeader(page, topMargin);
                    rowOffset = topMargin + headerHeight;
                }
                DrawReportRow(page, rowOffset, panels[i]);
                rowOffset = rowOffset + rowHeight;
            }
        }

        private static void DrawReportRow(PDFPage page, double topOffset, Control panel)
        {
            // Create the graphic objects
            PDFFont fontText = new PDFFont(PDFFontFace.Helvetica, 12);
            PDFPen borderColor = new PDFPen(new PDFRgbColor(), 1);
            PDFBrush textColor = new PDFBrush(new PDFRgbColor());
            PDFBrush headerFill = new PDFBrush(new PDFRgbColor(192, 192, 192));

            // Draw rows borders
            PDFPoint[] points = { new PDFPoint( leftMargin, topOffset ), 
                                  new PDFPoint( leftMargin, topOffset + rowHeight), 
                                  new PDFPoint( page.Width - rightMargin, topOffset + rowHeight ), 
                                  new PDFPoint( page.Width - rightMargin, topOffset )};
            page.Canvas.DrawLines(borderColor, points);

            double xOffset = leftMargin;
            // Draw the columns separators
            for (int i = 0; i < columnsWidth.Length - 1; i++)
            {
                xOffset = xOffset + columnsWidth[i];
                page.Canvas.DrawLine(borderColor, xOffset, topOffset,
                    xOffset, topOffset + rowHeight);
            }

            // Get all form fields from panel
            fields.Clear();
            GetFormFields(panel);

            xOffset = leftMargin;
            // Draw the columns header
            for (int i = 0; i < columnsWidth.Length; i++)
            {
                // Get ith field text 
                string fieldText = fields[i].Text;
                page.Canvas.DrawText(fieldText, fontText, null, textColor,
                    xOffset + 2, topOffset + rowHeight / 2, 0, PDFTextAlign.MiddleLeft);
                xOffset = xOffset + columnsWidth[i];
            }
        }

        private static void GetFormFields(Control panelControl)
        {
            ControlCollection controls = panelControl.Controls;
            foreach (Control childControl in panelControl.Controls)
            {
                if (childControl.GetType().ToString() == "System.Web.UI.WebControls.TextBox")
                {
                    TextBox txt = childControl as TextBox;
                    fields.Add(txt);
                }
                else
                {
                    GetFormFields(childControl);
                }
            }
        }

        protected void btnAddForm_Click(object sender, EventArgs e)
        {
            // Create Labels
            Label lblName = new Label();
            lblName.Text = "NAME:";
            Label lblNumber = new Label();
            lblNumber.Text = "NUMBER:";
            Label lblAddress = new Label();
            lblAddress.Text = "ADDRESS:";
            Label lblCompany = new Label();
            lblCompany.Text = "COMPANY:";

            // Create Text Boxes
            TextBox txtName = new TextBox();
            TextBox txtNumber = new TextBox();
            TextBox txtAddress = new TextBox();
            TextBox txtCompany = new TextBox();

            // Create submit button
            Button btnSubmit = new Button();
            btnSubmit.Text = "SUBMIT";

            // Create panel and add controls
            Panel pnlForm = new Panel();
            pnlForm.EnableViewState = true;
            pnlForm.Controls.Add(lblName);
            pnlForm.Controls.Add(txtName);
            pnlForm.Controls.Add(new LiteralControl("<br /><br />"));
            pnlForm.Controls.Add(lblNumber);
            pnlForm.Controls.Add(txtNumber);
            pnlForm.Controls.Add(new LiteralControl("<br /><br />"));
            pnlForm.Controls.Add(lblAddress);
            pnlForm.Controls.Add(txtAddress);
            pnlForm.Controls.Add(new LiteralControl("<br /><br />"));
            pnlForm.Controls.Add(lblCompany);
            pnlForm.Controls.Add(txtCompany);
            pnlForm.Controls.Add(new LiteralControl("<hr />"));
            pnlForm.Controls.Add(new LiteralControl("<br /><br />"));
            panels.Add(pnlForm);

            foreach (Control panel in panels)
            {
                phFormContent.Controls.Add(panel);
            }

        }

TextBoxes 被添加到 btnAddForm_Click() 函数中,并且在 DrawReportRow() 内部(它本身由另一个按钮单击事件触发)调用 GetFormFields(),它将所有动态添加的 TextBoxes 添加到静态列表中。这是 .aspx 文件....

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Form.aspx.cs" Inherits="PDFFormToGrid.Form" EnableViewState="true" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <asp:PlaceHolder ID="phFormContent" runat="server" EnableViewState="true">
            <asp:Panel ID="Panel1" runat="server" EnableViewState="true">
                <asp:Label ID="lblName" runat="server" Text="NAME:"></asp:Label>
                <asp:TextBox ID="txtName" runat="server"></asp:TextBox>
                <br /><br />
                <asp:Label ID="lblNumber" runat="server" Text="NUMBER:"></asp:Label>
                <asp:TextBox ID="txtNumber" runat="server"></asp:TextBox>
                <br /><br />
                <asp:Label ID="lblAddress" runat="server" Text="ADDRESS:"></asp:Label>
                <asp:TextBox ID="txtAddress" runat="server"></asp:TextBox>
                <br /><br />
                <asp:Label ID="lblCompany" runat="server" Text="COMPANY:"></asp:Label>
                <asp:TextBox ID="txtCompany" runat="server"></asp:TextBox>
                <hr />
                <br /><br />
            </asp:Panel>
        </asp:PlaceHolder>
        <br /><br />
        <asp:Button ID="btnAddForm" runat="server" Text="Add Form" OnClick="btnAddForm_Click" />
        <asp:Button ID="btnSubmitForms" runat="server" Text="Submit Forms" OnClick="btnSubmit_Click" />
    </form>
</body>
</html>

【问题讨论】:

    标签: c# asp.net dynamic webforms viewstate


    【解决方案1】:

    在您的 btnAddForm_Click 方法中,您要确保为字段提供一致的控件 ID,例如:

    // Create Text Boxes
    TextBox txtName = new TextBox();
    txtName.ID = "txtName";
    TextBox txtNumber = new TextBox();
    txtNumber.ID = "txtNumber";
    TextBox txtAddress = new TextBox();
    txtAddress.ID = "txtAddress";
    TextBox txtCompany = new TextBox();
    txtCompany.ID = "txtCompany";
    

    然后在您的 btnSubmitForm_Click 方法中,您可以通过 Linq 抓取占位符内的所有面板,例如:

    var panelFields = (from panel in phFormContent.Controls.OfType<Panel>()
                                    let txtName = panel.FindControl<TextBox>("txtName")
                                    let txtNumber = panel.FindControl<TextBox>("txtNumber")
                                    let txtAddress = panel.FindControl<TextBox>("txtAddress")
                                    let txtCompany = panel.FindControl<TextBox>("txtCompany")
                                    select new
                                    {
                                         Name = txtName.Text,
                                         Number = txtNumber.Text,
                                         Address = txtAddress.Text,
                                         Company = txtCompany.Text
                                    }).ToList();
    
    
    foreach (var fields in panelFields)
    {
        Response.Write(string.Format("{0} {1} {2} {3}<br />", fields.Name, fields.Number, fields.Address, fields.Company));
    }
    

    更新

    我只是想为未来的谷歌员工注意这一点,因为我误读了这个问题,还有另一个问题,因为页面生命周期要求您必须在回发时重新创建动态控件:

    编辑以在回发时重新创建动态控件

    我只是展示了从上面更改的主要方法。

    // creates 1 panel on the first load
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!Page.IsPostBack)
        {
            FormCount = 1;
        }
        CreatePanels();
    }
    
    // first line is added to grab the all panels in phFormContent before passing to the pdf creation routine
    protected void btnSubmit_Click(object sender, EventArgs e)
    {
        panels = phFormContent.Controls.OfType<Panel>().ToList();
        PDFDocument form = CreatePDF(this);
    
        Response.ContentType = "application/x-msdownload";
        Response.AddHeader("content-disposition", "attachment;filename=form.pdf");
        form.Save(Response.OutputStream);
        Response.Flush();
        Response.End();
    }
    
    // when adding we just inc the form counter and add a panel
    protected void btnAddForm_Click(object sender, EventArgs e)
    {
        FormCount = FormCount + 1;
        CreatePanel();
    }
    
    // routine to create the form panels
    protected void CreatePanels()
    {
        for (int i = 0; i < FormCount; i++)
        {
            CreatePanel();
        }
    }
    // this just creates a panel now and appends to placeholder;
    protected void CreatePanel()
    {
        // Create Labels
        Label lblName = new Label();
        lblName.Text = "NAME:";
        Label lblNumber = new Label();
        lblNumber.Text = "NUMBER:";
        Label lblAddress = new Label();
        lblAddress.Text = "ADDRESS:";
        Label lblCompany = new Label();
        lblCompany.Text = "COMPANY:";
    
        // Create Text Boxes
        TextBox txtName = new TextBox();
        TextBox txtNumber = new TextBox();
        TextBox txtAddress = new TextBox();
        TextBox txtCompany = new TextBox();
    
        // Create submit button
        Button btnSubmit = new Button();
        btnSubmit.Text = "SUBMIT";
    
        // Create panel and add controls
        Panel pnlForm = new Panel();
        pnlForm.EnableViewState = true;
        pnlForm.Controls.Add(lblName);
        pnlForm.Controls.Add(txtName);
        pnlForm.Controls.Add(new LiteralControl("<br /><br />"));
        pnlForm.Controls.Add(lblNumber);
        pnlForm.Controls.Add(txtNumber);
        pnlForm.Controls.Add(new LiteralControl("<br /><br />"));
        pnlForm.Controls.Add(lblAddress);
        pnlForm.Controls.Add(txtAddress);
        pnlForm.Controls.Add(new LiteralControl("<br /><br />"));
        pnlForm.Controls.Add(lblCompany);
        pnlForm.Controls.Add(txtCompany);
        pnlForm.Controls.Add(new LiteralControl("<hr />"));
        pnlForm.Controls.Add(new LiteralControl("<br /><br />"));
        phFormContent.Controls.Add(pnlForm);
    }
    
    // keeps track of how many panels we need to recreate.
    public int FormCount
    {
        get
        {
            if (ViewState["FormCount"] != null)
            {
                return (int)ViewState["FormCount"];
            }
    
            return 1;
        }
        set
        {
            ViewState["FormCount"] = value;
        }
    }
    

    由于第一个页面请求添加了第一个面板,因此占位符可以为空:

    <asp:PlaceHolder ID="phFormContent" runat="server" EnableViewState="true"></asp:PlaceHolder>
    

    【讨论】:

    • 很酷,我得到了数据。谢谢卢克!
    • 我在回答问题后注意到我看错了。我只是注意到这一点,以防有人采取与您不同的道路。当您动态添加控件时,您必须在回发时重新创建它们。我将使用该结果编辑我的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-05-16
    • 1970-01-01
    • 1970-01-01
    • 2019-11-08
    • 2019-03-27
    • 1970-01-01
    • 2021-06-17
    相关资源
    最近更新 更多