无法从动态添加的文本框中获取值

时间:2013-07-14 14:39:36

标签: c# asp.net dynamic webforms viewstate

尽我所能我无法从动态添加的文本框中获取值。我已尝试在所有包含控件中启用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()被调用,它将所有动态添加的TextBox添加到静态List。这是.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>

1 个答案:

答案 0 :(得分: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));
}

更新

我只是想为未来的googlers注意这一点,因为我误读了这个问题并且还有另一个问题因为页面生命周期决定你必须在回发时重新创建动态控件:

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

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

// 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>