2017-03-24 3 views
1

동적으로 생성 된 사용자 정의 컨트롤에서 선택한 값을 유지하는 데 어려움이 있습니다. 몇 가지 양식 필드가있는 usercontrol을 만들었습니다. 메인 페이지에는 placeholder에 내 usercontrol을 배치 할 버튼이 있습니다. 사용자는 필요한만큼 많은 것을 만들 수 있습니다. 또한 사용자가 컨트롤을 삭제할 수있는 컨트롤 자체에 단추가 있습니다. 이 기능은 정상적으로 작동하는 것 같습니다.포스트 백에서 동적으로 생성 된 usercontrols의 이상한 동작

는하지만, 불가사의는 다음 시나리오에서 계속된다 :

  1. 클릭 버튼이 페이지에 UserControl을을 만들 수 있습니다. 양식 을 작성하십시오.
  2. 버튼을 다시 클릭하여 두 번째 UC를 만들고 양식 필드를 작성하십시오. 이 시점에서 모든 것이 잘됩니다. UC# 1의 값은 값을 유지했습니다.
  3. 버튼을 클릭하여 세 번째 UC를 만들고 선택한 값은 모두 UC# 1 및 # 2에서 닦여진 입니다.
  4. 모든 UC의 필드를 다시 채우고 버튼을 클릭하여 4 번째 UC를 만들면 UC# 1과 UC# 3은 값을 유지하지만 UC# 2는 값을 잃습니다.

모든 도움을 주시면 감사하겠습니다. 나는 이걸 알아 내려고 눈을 멀게하려고한다. 이것은 동적 인 usercontrols에 나의 첫발을 내디뎠다. 그리고 지금까지 그것은 나의 엉덩이를 차고있다. 그리고 나는이 UC에 db 값을 채우는 방법을 알아야하므로 사용자가 다시 돌아와서 폼을 편집 할 수 있습니다.하지만 한 번에 한 가지만 할 수 있습니다.

영문 :

<asp:PlaceHolder ID="placeholderOffenseCodes" runat="server"> </asp:PlaceHolder> 
    <asp:Button ID="btnAddOffense" runat="server" Text="Add an Offense" CausesValidation="false" OnClick="btnAddOffense_Click" /> 
<!--The text value determines how many items are initially displayed on the page--> 
    <asp:Literal ID="ltlCount" runat="server" Text="0" Visible="false" /> 
    <asp:Literal ID="ltlRemoved" runat="server" Visible="false" /> 

aspx.cs :

protected void Page_Load(object sender, EventArgs e) 
{ 
    AddAndRemoveDynamicOffenseControls(); 
} 

private void AddAndRemoveDynamicOffenseControls() 
{ 
    //Determine which control fired the postback event. 
    Control c = GetPostBackOffenseControl(Page); 

    if ((c != null)) 
    { 
     //If the add button was clicked, increase 
     //the count to let the page know we want 
     //to display an additional user control 
     if (c.ID.ToString() == "btnAddOffense") 
     { 
      ltlCount.Text = Convert.ToString(Convert.ToInt16(ltlCount.Text) + 1); 
     } 
    } 

    //Be sure everything in the placeholder control is cleared out 
    placeholderOffenseCodes.Controls.Clear(); 

    int ControlID = 0; 

    //Re-add controls every time the page loads. 
    for (int i = 0; i <= (Convert.ToInt16(ltlCount.Text) - 1); i++) 
    { 
     IncidentGroupA_Offenses uc = (IncidentGroupA_Offenses)LoadControl("IncidentGroupA_Offenses.ascx"); 

     //If this particular control id has been deleted 
     //from the page, DO NOT use it again. If we do, it will 
     //pick up the viewstate data from the old item that 
     //had this control id, instead of generating 
     //a completely new control. Instead, increment 
     //the control ID so we're guaranteed to get a "new" 
     //control that doesn't have any lingering information in the viewstate. 
     while (InDeletedOffenseList("offense" + ControlID) == true) 
     { 
      ControlID += 1; 
     } 

     //Note that if the item has not been deleted from the page, 
     //we DO want it to use the same control id 
     //as it used before, so it will automatically maintain 
     //the viewstate information of the user control 
     //for us. 
     uc.ID = "offense" + ControlID; 

     //Add an event handler to this control to raise 
     //an event when the delete button is clicked 
     //on the user control 
     uc.RemoveOffenseUC += this.HandleRemoveOffenseUserControl; 

     //Add the user control to the panel 
     placeholderOffenseCodes.Controls.Add(uc); 

     //Add Offense number to label on usercontrol 
     int OffenseNum = i + 1; 
     uc.OffenseNumber = "Offense " + OffenseNum; 

     //Increment the control id for the next round through the loop 
     ControlID += 1; 
    } 
} 

protected void btnAddOffense_Click(object sender, EventArgs e) 
{ 
    //handled in page_load 
} 

private bool InDeletedOffenseList(string ControlID) 
{ 
    //Determine if the passed in user control ID 
    //has been stored in the list of controls that 
    //were previously deleted off the page 
    string listvalues = ltlRemoved.Text; 
    string[] stringSeparators = new string[] { "|" }; 
    string[] DeletedList = listvalues.Split(stringSeparators, StringSplitOptions.RemoveEmptyEntries); 
    for (int i = 0; i <= DeletedList.GetLength(0) - 1; i++) 
    { 
     if (ControlID == DeletedList[i]) 
     { 
      return true; 
     } 
    } 
    return false; 
} 

public void HandleRemoveOffenseUserControl(object sender, EventArgs e) 
{ 
    //This handles delete event fired from the user control 

    //Get the user control that fired this event, and remove it 
    LinkButton linkBtn = sender as LinkButton; 
    IncidentGroupA_Offenses uc = (IncidentGroupA_Offenses)linkBtn.Parent; 

    if (uc != null) 
    { 
     placeholderOffenseCodes.Controls.Remove(uc); 
    } 

    //Keep a pipe delimited list of which user controls were removed. This will increase the 
    //viewstate size if the user keeps removing dynamic controls, but under normal use 
    //this is such a small increase in size that it shouldn't be an issue. 
    ltlRemoved.Text += uc.ID.ToString() + "|"; 

    //Also, now that we've removed a user control decrement the count of total user controls on the page 
    ltlCount.Text = Convert.ToString(Convert.ToInt16(ltlCount.Text) - 1); 
} 

public Control GetPostBackOffenseControl(Page page) 
{ 
    Control control = null; 

    string ctrlname = page.Request.Params.Get("__EVENTTARGET"); 
    if ((ctrlname != null) & ctrlname != string.Empty) 
    { 
     control = page.FindControl(ctrlname); 
    } 
    else 
    { 
     foreach (string ctl in page.Request.Form) 
     { 
      Control c = page.FindControl(ctl); 
      if (c is System.Web.UI.WebControls.Button) 
      { 
       control = c; 
       break; 
      } 
     } 
    } 
    return control; 
} 

.ascx.cs는 :

public event EventHandler RemoveOffenseUC; 

protected void btnRemoveOffense_Click(object sender, EventArgs e) 
{ 
    //Raise this event so the parent page can handle it 
    if (RemoveOffenseUC != null) 
    { 
     RemoveOffenseUC(sender, e); 
    } 
} 

public string OffenseNumber 
{ 
    get { return lblOffenseNumber.Text; } 
    set { lblOffenseNumber.Text = value; } 
} 

답변

0

나는 항상 당신이 올바른을 보장하기 위해 후 Page_Init에서 동적 컨트롤을 추가 할 수 있다고 생각 ViewState의로드. 어쩌면 그 간단한 변화가 당신의 문제를 해결할 수 있을까요?

그렇지 않으면 과거에는 리피터를 사용하여 다이나믹 컨트롤을 피하는 것이 좋았습니다. 분명히 좋지 않은 동적 인 컨트롤을 추가하는 대신 List 또는 ADO DataTable과 같은 데이터 구조에 데이터를 추가 한 다음 원하는 컨트롤을 사용하여 asp : Repeater에 바인딩합니다. 동적 컨트롤로 번거롭게 번거롭지 않습니다.

행운을 빈다.

+0

감사합니다. 지금 코드를 Page_Init으로 이동하려고합니다. – Wilock

관련 문제