Динамические созданные элементы управления внутри UpdatePanel?
-
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
}