0

尽我所能尝试我无法从动态添加的文本框中获取值。我尝试在所有包含控件中启用 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);
            }

        }

在 btnAddForm_Click() 函数中添加文本框,在 DrawReportRow() 内部(它本身由另一个按钮单击事件触发)调用 GetFormFields(),它将所有动态添加的文本框添加到静态列表中。这是 .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>
4

1 回答 1

0

在您的 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>
于 2013-07-14T15:04:54.880 回答