Динамические созданные элементы управления внутри UpdatePanel?

StackOverflow https://stackoverflow.com/questions/4086320

  •  28-09-2019
  •  | 
  •  

Вопрос

Я хочу создать контроль, который позволит пользователю создавать свой собственный веб-сайт. Я представлял, что внутри UpdatePanel контролирует (ы) с TextBox (для имени страницы) и Button «Добавьте ниже». Это выглядит как:

|   "Questions" |
| [ add below ] |

|     "Tags"    |
| [ add below ] |

|    "Badges"   |
| [ add below ] |

Теперь, когда пользователь нажимает на кнопку в элементе «Теги», там должен появиться новый, между «тегами» и «значками», с редактируемым именем, поэтому пользователь может назвать его «пользователям», например. Это должно быть сделано без полной отступности (чтобы избежать миганий страницы).

Сейчас моя проблема: я не могу загрузить эти элементы управления (наконец-то не все их) в Oninit, поскольку они не существуют, но я должен принять участие в их событии, поэтому я должен подключить слушатель события, что должно быть сделано во время фазы INIT. Как я могу достичь описанной функциональности?

Я играл вокруг этого слишком много времени, и я запутался. Буду благодарен за любые советы.

Это было полезно?

Решение

Это сложная ситуация, потому что вы имеете дело с динамическими элементами управления, вам нужно заполнить их на странице init, чтобы продолжить возможность просмотра, а также события для элементов управления, добавленные внутри панели обновления во время нажима на кнопку, которые не могут быть зарегистрированы до следующей записи, так Нормальная кнопка Нажмите событие только один раз в другое время, когда вы нажимаете на недавно добавленный элемент управления. Там может быть какой-то другой способ работать вокруг этого, чем я это сделал. Если кто-то знает, что я хотел бы узнать.

Мое решение состоит в том, чтобы сохранить список того, что вы динамически добавили, и храните его в переменную сеанса (потому что ViewState не загружается на странице init). Затем на странице init загрузите любые элементы управления, которые вы ранее добавили. Затем обратитесь к событию Click во время нагрузки на страницу с помощью какого-либо пользовательского кода или нормального события Click.

Я создал образец страницы, чтобы помочь тестировать это.

Вот код для страницы ASPX (по умолчанию .aspx):

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
    <p>This only updates on full postbacks: <%= DateTime.Now.ToLongTimeString() %></p>
    <asp:UpdatePanel ID="UpdatePanel1" runat="server">
        <ContentTemplate>
            <asp:PlaceHolder ID="PlaceholderControls" runat="server"></asp:PlaceHolder>
        </ContentTemplate>
    </asp:UpdatePanel>
    </form>
</body>
</html>

И вот код для кода за страницей (по умолчанию .aspx.cs):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class _Default : System.Web.UI.Page
{
    /// <summary>
    /// this is a list for storing the id's of dynamic controls
    /// I have to put this in the session because the viewstate is not
    /// loaded in the page init where we need to use it
    /// </summary>
    public List<string> DynamicControls
    {
        get
        {
            return (List<string>)Session["DynamicControls"];
        }
        set
        {
            Session["DynamicControls"] = value;
        }
    }

    protected void Page_Init(object sender, EventArgs e)
    {
        PlaceholderControls.Controls.Clear();

        //add one button to top that will cause a full postback to test persisting values--
        Button btnFullPostback = new Button();
        btnFullPostback.Text = "Cause Full Postback";
        btnFullPostback.ID = "btnFullPostback";
        PlaceholderControls.Controls.Add(btnFullPostback);

        PlaceholderControls.Controls.Add(new LiteralControl("<br />"));

        PostBackTrigger FullPostbackTrigger = new PostBackTrigger();
        FullPostbackTrigger.ControlID = btnFullPostback.ID;

        UpdatePanel1.Triggers.Add(FullPostbackTrigger);
        //-----------------------------------------------------------------------




        if (!IsPostBack)
        {
            //add the very first control           
            DynamicControls = new List<string>();

            //the DynamicControls list will persist because it is in the session
            //the viewstate is not loaded yet
            DynamicControls.Add(AddControls(NextControl));

        }
        else
        {
            //we have to reload all the previously loaded controls so they
            //will have been added to the page before the viewstate loads
            //so their values will be persisted
            for (int i = 0; i < DynamicControls.Count; i++)
            {
                AddControls(i);
            }
        }


    }

    protected void Page_Load(object sender, EventArgs e)
    {

        if (!IsPostBack)
        {
            //we have to increment the initial
            //control count here here be cause we cannot persit data in the viewstate during 
            //page init

            NextControl++;

        }
        else
        {
            HandleAddNextClick();           

        }

    }

    /// <summary>
    /// this function looks to see if the control which caused the postback was one of our 
    /// dynamically added buttons, we have to do this because the update panel seems to interefere
    /// with the event handler registration.
    /// </summary>
    private void HandleAddNextClick()
    {
        //did any of our dynamic controls cause the postback if so then handle the event
        if (Request.Form.AllKeys.Any(key => DynamicControls.Contains(key)))
        {
            DynamicControls.Add(AddControls(NextControl));
            NextControl++;
        }
    }



    protected void btnAddNext_Command(object sender, CommandEventArgs e)
    {
        //this is intentionally left blank we are handling the click in the page load
        //because the event for controls added dynamically in the click does
        //not get registered until after a postback, so we have to handle it 
        //manually.  I think this has something to do with the update panel, as it works 
        //when not using an update panel, there may be some other workaround I am not aware of

    }

    /// <summary>
    /// variable for holding the number of the next control to be added
    /// </summary>
    public int NextControl
    {
        get
        {
            return  ViewState["NextControl"] == null ? 0 : (int)ViewState["NextControl"];
        }
        set
        {
            ViewState["NextControl"] = value;
        }
    }


    /// <summary>
    /// this function dynamically adds a text box, and a button to the placeholder
    /// it returns the UniqueID of the button, which is later used to find out if the button
    /// triggered a postback
    /// </summary>
    /// <param name="ControlNumber"></param>
    /// <returns></returns>
    private string AddControls(int ControlNumber)
    {
        //add textbox
        TextBox txtValue = new TextBox();
        txtValue.ID = "txtValue" + ControlNumber;
        PlaceholderControls.Controls.Add(txtValue);

        //add button
        Button btnAddNext = new Button();
        btnAddNext.Text = "Add Control " + ControlNumber;
        btnAddNext.ID = "btnAddNext" + ControlNumber;
        int NextControl = ControlNumber + 1;
        btnAddNext.CommandArgument = NextControl.ToString();

        btnAddNext.Command += new CommandEventHandler(btnAddNext_Command);
        PlaceholderControls.Controls.Add(btnAddNext);

        //add a line break
        PlaceholderControls.Controls.Add(new LiteralControl("<br />"));

        return btnAddNext.UniqueID;

    }    
}

Дайте мне знать, если этот код поможет вам вообще. Я пытался добавить комментарии с моим пониманием того, что происходит и как это работает.

Другие советы

Этот способ работает для меня

   protected void Page_Load(object sender, EventArgs e)
    {
        if (Page.IsPostBack)
        {
            Button_Click(null, null);
        }
    }

В кнопке вызов

 protected void Button_Click(object sender, EventArgs e)
    {
            Panel1.Controls.Clear();
            this.YourMethod();
        }
    }

Прежде чем позвонить на метод очистить контроль иначе он будет загружаться дважды

Если вы хотите динамически Divershandlers для ваших элементов управления, вы можете попробовать это -

Учитывая кнопку управления,

Button btnTest = new Button();
btnTest .Click += new EventHandler(btnTest_Click);

Вы можете иметь свой код в кнопке нажмите событие,

void btnTest_Click(object sender, EventArgs e)
{
    //your code
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top