이 문제는 문제를 일으키지 않습니다! 요구 사항은 사용자가 동일한 유형의 pf 데이터의 여러 인스턴스를 추가하기위한 컨트롤 행을 추가 및 삭제할 수있는 웹 양식 (C#/ASP.Net Webform으로 작성)에 대한 것입니다.순차적으로 번호가 매겨진 컨트롤에 액세스하기 C# 코드 뒤
이 페이지는 내가 MasterPages 어려움으로 실행될 수 있도록 MasterPages의 계층 구조를 가지고 더 큰 사이트의 존재 ...
내 문제는이 "테이블"에서 행을 삭제 특별히입니다. 좋았던 것을 위해 또는 나는 병이 여러 패널을 가지고있는 패널로 만들었다. 각 하위 패널은 내 "테이블"의 한 행을 나타냅니다.
내 addRow 버튼이 완벽하게 작동합니다. 그러나 deleteRow 버튼은 어떻게 처리 할 것인가에 따라 다른 방식으로 실패합니다.
- 삭제 버튼에 대한 EventHandler를 등록하면 이벤트가 실행되고 메모리에서 행이 삭제되지만 다른 버튼을 클릭 할 때까지 페이지에 남아 있습니다 (두 번째 PostBack 이벤트가 발생 함).
- JavaScript __doPostBack 방식을 사용하면 내 Page_Load 메서드에서 이벤트에 액세스 할 수 있지만 삭제하려는 행에 대한 객체 참조를 가져올 수 없습니다!
<%@ 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); } } }
내가 여기
내 (관련 부분에 트리밍) default.aspx에있다 렌더링 된 HTML을 추가하려고했지만 새 글자 수를 초과했습니다. 요약
:이
이 이해가 왜 'BtnDeleteRow_Click은() 핸들러는 내가 원하는 방식으로 작동하지 않는, 그래서 내가 삭제 이벤트를 잡을 수있는 희망의'__doPostBack '를 사용으로 전환 페이지 수명주기의 초기 단계 나는 Page_load에서 그것을 잡을 수 있는데, 나는 달콤한 자리라고 생각한다. (내 ViewState가로드되어서 내 행 인덱스에 액세스 할 수 있지만 페이지는 렌더링되지 않았다.) 그러나 나는 클릭 한 실제 버튼에 대한 어떤 종류의 객체 참조도 얻을 수 없으므로 앞으로 나아갈 수 없습니다. Page_load에 도착하면 'Request [ "EVENTTARGET"]'에 올바른 ID가 있습니다.
을도 코멘트하지 않고 내 질문에 투표 한 익명의 유권자에 - 나는 내 문제를 연구 어제의 대부분을 보냈다 유용한 결과가 없기 때문에 여러 가지 방법을 시도하여 혼자서 해결했으며 마지막으로 누군가가 유용한 제안을하기를 희망하여 게시했습니다. – cptully