时间:2017-11-07 18:40:10

标签: javascript c# asp.net webforms dopostback

这个问题让我无穷无尽!要求是Web表单(用C#/ ASP.Net Webforms编写),用户可以在其中添加和删除控件行,以添加相同类型的pf数据的多个实例。

此页面存在于一个更大的站点中,该站点具有MasterPages层次结构,因此我可能遇到MasterPages的困难......

我的问题是专门从这个"表"中删除一行。为了好或坏我把它建成一个面板,保持多个子面板。每个子面板代表我的"表"。

的一行

我的addRow按钮完美运行。但deleteRow按钮以不同的方式失败,具体取决于我尝试处理它们的方式。

  • 如果我为删除按钮注册一个EventHandler,则会触发事件,并且该行将在内存中删除,但会保留在页面上,直到单击另一个按钮(导致第二个PostBack事件)。
  • 如果我使用JavaScript __doPostBack方法,我可以在我的Page_Load方法中访问该事件,但我无法获得对我要删除的行的对象引用!

这是我的default.aspx(修剪到相关部分):

<%@ Page Title="Alumni Outreach" Language="C#" EnableViewState="true" MasterPageFile="~/components/navigation/sidebar.master" AutoEventWireup="true" CodeBehind="default.aspx.cs" Inherits="www.law.unc.edu.alumni.outreach.outreach2" %>
<%@ MasterType VirtualPath="~/components/navigation/sidebar.master"%>

<asp:Content ID="Content1" ContentPlaceHolderID="cphContent1" runat="server">
    <asp:Panel ID="pnlInformation" runat="server">
        <h1>Community Outreach
        </h1>
        <p>
            <span class="carolinaBlue">Purpose:</span> To quantify the UNC School of Law's <span class="carolinaBlue">Legacy of Leadership
            </span>via Carolina Law alumni's stories of service, volunteerism, and leadership across the state and nation. Information gathered will be utilized in a variety of Carolina Law communnications/marketing pieces (for instance, an online presence with interactive maps) designed to illustrate Carolina Law alumni's leadership in the communities where they live and work.
        </p>
    </asp:Panel>
    <asp:Panel ID="pnlForm" runat="server">


        <h2>Volunteer Leadership Roles</h2>
        <p>
            Please share your commitment to community leadership by noting all organizations you have voluntarily served below.
        </p>
        <div style="display: inline-block;">
            <asp:Button ID="btnAddLeadershipRow" OnClick="BtnAddLeadershipRow_Click" Text="+" runat="server" />
        </div>
        <div style="display: inline-block">
            <div style="display: inline-block; width: 6.5em; font: 700 1em Verdana,Arial,Sans-Serif !important">Region</div>
            <div style="display: inline-block; width: 7em; font: 700 1em Verdana,Arial,Sans-Serif !important">Profit?</div>
            <div style="display: inline-block; width: 20.5em; font: 700 1em Verdana,Arial,Sans-Serif !important">Organization</div>
            <div style="display: inline-block; width: 14em; font: 700 1em Verdana,Arial,Sans-Serif !important">Position</div>
        </div>
        <asp:Panel ID="pnlLeadershipFields" runat="server">
            <!-- dynamically add controls here -->
        </asp:Panel>
</asp:Content>

以下是我的default.aspx.cs文件的相关部分:

using System;
using System.Collections.Generic;
using System.Web.UI;
using System.Web.UI.WebControls;
using BusinessLogic.Alumni.Outreach;
using System.Text.RegularExpressions;

namespace www.law.unc.edu.alumni.outreach
{
    [ViewStateModeById]
    public partial class outreach2 : System.Web.UI.Page
    {
        private List<String> regions;
        private List<String> profit;
        private List<Button> _foundControls = new List<Button>();

        public outreach2()
        {
            regions = new List<string> {
                "Local",
                "State",
                "National"
            };

            profit = new List<string> {
                "Non-Profit",
                "For-Profit"
            };
        }

        protected int LeadershipControlsMaxIndex
        {
            get {
                if (ViewState["LeadershipControlsMaxIndex"] == null)
                    ViewState.Add("LeadershipControlsMaxIndex", 0);
                return (int)ViewState["LeadershipControlsMaxIndex"];
            }
            set {
                if (ViewState["LeadershipControlsMaxIndex"] == null)
                    ViewState.Add("LeadershipControlsMaxIndex", value);
                else
                    ViewState["LeadershipControlsMaxIndex"] = value;
            }
        }

        protected List<int> LeadershipControlsIndexes
        {
            get { 
                if (!(ViewState["LeadershipControlsIndexes"] is List<int>))
                {
                    ViewState["LeadershipControlsIndexes"] = new List<int>();
                }
                return (List<int>)ViewState["LeadershipControlsIndexes"];
            }
            set { ViewState["LeadershipControlsIndexes"] = value; }
        }

        // If this is the first time the user is visiting the page 
        //  create one set of controls
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!Page.IsPostBack)
            {
                CreateLeadershipControl();
            }
            else if (Page.IsPostBack)
            {
                // if I do:
                // btnDelete.OnClientClick = "javascript:__doPostBack(\""+btnDelete.ID+"\",\"\")";
                // when creating the delete button I enter the following if
                // clause but cannot get an object (or Control or Button)
                // reference to the btnDelete, whether I use this.Form or
                // pnlLeadershipFields in the call to FindChildControlsRecursive
                if (Request["__EVENTTARGET"].Contains("btnLeadershipRowDelete"))
                {
                    FindChildControlsRecursive(this.Form);
                    object btnDelete = _foundControls.Find(x => x.ID == Request["__EVENTTARGET"]);
                    DeleteControls(btnDelete);
                }
                RecreateLeadershipControls();
            }
        }

        public void FindChildControlsRecursive(Control control)
        {
            foreach (Control childControl in control.Controls)
            {
                if (childControl.GetType() == typeof(Button))
                {
                    _foundControls.Add((Button)childControl);
                }
                else
                {
                    FindChildControlsRecursive(childControl);
                }
            }
        }

        private void CreateLeadershipControl()
        {
            LeadershipControlsMaxIndex++;
            LeadershipControlsIndexes.Add(LeadershipControlsMaxIndex - 1);
            AddLeadershipControls(LeadershipControlsIndexes[LeadershipControlsIndexes.Count - 1]);
        }

        private void RecreateLeadershipControls()
        {
            List<int> indexes = LeadershipControlsIndexes;

            for (int i = 0; i < indexes.Count; i++)
            {
                AddLeadershipControls(indexes[i]);
            }
        }

        private void AddLeadershipControls(int index)
        {
            Panel pnlLeadershipControls = new Panel
            {
                ID = "LeadershipControls" + index.ToString(),
                CssClass = "pnlControls"
            };

            Button btnDelete = new Button()
            {
                ID = "btnLeadershipRowDelete" + index.ToString(),
                Text = "-"
            };
            //btnDelete.Click += new EventHandler(BtnDeleteRow_Click);
            btnDelete.OnClientClick = "javascript:__doPostBack(\""+btnDelete.ID+"\",\"\")";
            btnDelete.Attributes.Add("style", "display: inline-block; width: 1.4em;");
            pnlLeadershipControls.Controls.Add(btnDelete);

            DropDownList ddlRegion = new DropDownList
            {
                DataSource = regions,
                ID = "LeadershipRegion" + index.ToString()
            };
            ddlRegion.DataBind();
            ddlRegion.Attributes.Add("style", "display: inline-block; width: 7em;");
            pnlLeadershipControls.Controls.Add(ddlRegion);

            DropDownList ddlProfit = new DropDownList
            {
                DataSource = profit,
                ID = "LeadershipProfit" + index.ToString(),
                CssClass = "ddlProfit"
            };
            ddlProfit.DataBind();
            ddlProfit.Attributes.Add("style", "display: inline-block; width: 7.5em;");
            pnlLeadershipControls.Controls.Add(ddlProfit);

            TextBox txtOrg = new TextBox
            {
                ID = "txtLeadershipOrganization" + index.ToString()
            };
            txtOrg.Attributes.Add("style", "display: inline-block; width: 20em;");
            pnlLeadershipControls.Controls.Add(txtOrg);

            TextBox txtPos = new TextBox
            {
                ID = "txtLeadershipPosition" + index.ToString()
            };
            txtPos.Attributes.Add("style", "display: inline-block; width: 20em;");
            pnlLeadershipControls.Controls.Add(txtPos);

            CheckBox cbCurrent = new CheckBox
            {
                ID = "cbLeadershipCurrent" + index.ToString(),
                Text = "Current?",
            };
            cbCurrent.Attributes.Add("style", "display: inline-block; font: 700 1em Verdana,Arial,Sans-Serif !important");
            pnlLeadershipControls.Controls.Add(cbCurrent);

            pnlLeadershipFields.Controls.Add(pnlLeadershipControls);
        }


        private void DeleteControls(object sender)
        {
            Button button = (Button)sender;
            string id = button.ID;
            int index = Int32.Parse(Regex.Match(id, @"\d+$").Value);
            Panel row = (Panel)button.Parent;

            for (int i = row.Controls.Count - 1; i >= 0; i--)
            {
                if (row.Controls[i] is Button)
                    ((Button)row.Controls[i]).Click -= new EventHandler(BtnDeleteRow_Click);
                row.Controls[i].Dispose();
            }
            row.Parent.FindControl(row.ID).Dispose();
            if (id.Contains("Leadership"))
            {
                LeadershipControlsIndexes.RemoveAt(LeadershipControlsIndexes.FindIndex(x => x == index));
            }
        }

        protected void BtnAddLeadershipRow_Click(object sender, EventArgs e)
        {
            CreateLeadershipControl();
        }

        // If I do:
        // btnDelete.Click += new EventHandler(BtnDeleteRow_Click);
        // when creating the delete button, this method is called,
        // but too late in the page life cycle
        protected void BtnDeleteRow_Click(object sender, EventArgs e)
        {
            DeleteControls(sender);
        }
    }
}

我尝试添加呈现的HTML,但是超过了新帖子的字符限制!

总结:

我理解为什么&#39; BtnDeleteRow_Click()&#39;处理程序没有按照我想要的方式工作,所以我转而使用&#39; __ doPostBack&#39;希望我能在页面生命周期的早期发现删除事件。我可以在Page_load中捕获它,我认为这是最佳点(我的ViewState已被加载,因此我可以访问我的行索引,但页面尚未呈现)。但由于我无法获得任何类型的对象引用被点击的实际按钮,我无法前进。当我到达Page_load时,我确实在&#39;请求[&#34; __ EVENTTARGET&#34;]&#39;中有正确的ID。

1 个答案:

答案 0 :(得分:0)

如果我理解你的目标,我会考虑使用UpdatePanel中包含的ListView来实现这种功能。以下示例使用表,但如果没有它们,您可以根据需要格式化表单:

https://www.codeproject.com/Articles/44070/Insert-a-new-record-using-ListView-with-a-GridView