我希望用户能够通过单击UserControl内的“删除”按钮来删除UserControl。
btnAddChoice工作正常但是btnRemove在UserControl中并且没有触发btnRemove_Click。
这是我的ShowChoices.aspx代码:
<div>
<strong>Choices</strong>
<asp:UpdatePanel ID="UpdatePanel1" runat="server" ChildrenAsTriggers="true">
<Triggers>
<asp:AsyncPostBackTrigger ControlID="btnAddChoice" EventName="Click" />
</Triggers>
<ContentTemplate>
<ul class="list-unstyled">
<asp:PlaceHolder runat="server" ID="phChoices">
</asp:PlaceHolder>
</ul>
</ContentTemplate>
</asp:UpdatePanel>
</div>
这是我的ShowChoices.aspx.cs代码:
protected void btnAddChoice_Click(object sender, EventArgs e)
{
Choice ctl = (Choice)LoadControl("~/Controls/Choice.ascx");
ctl.ID = "choice" + PersistedControls.Count;
int j = PersistedControls.Count + 1;
ctl.SetSummary("Choice #" + j);
phChoices.Controls.Add(ctl); // the UserControl is added here
PersistedControls.Add(ctl);
AsyncPostBackTrigger trigger = new AsyncPostBackTrigger();
trigger.ControlID = ctl.BtnRemoveUniqueID; // problem : BtnRemoveUniqueID = always null
trigger.EventName = "Click";
UpdatePanel1.Triggers.Add(trigger);
}
在Choice.ascx中:
<asp:Button ID="btnRemove" CssClass="btn-default" runat="server" Text="Remove this choice" CausesValidation="false" OnClick="btnRemove_Click"/>
在Choice.ascx.cs
中protected void btnRemove_Click(object sender, EventArgs e)
{
this.Parent.Controls.Remove(this);
List<Control> _persistedControls = (List<Control>) Session[Step2.PersistedControlsSessionKey];
_persistedControls.Remove(this);
Session[Step2.PersistedControlsSessionKey] = _persistedControls;
UpdatePanel ctl = (UpdatePanel) this.Parent.FindControl("UpdatePanel1");
if (ctl != null)
{
ctl.Update();
}
}
答案 0 :(得分:1)
用户控件创建一个单独的命名容器,这意味着您的更新面板需要额外的工作(这里的答案很好地解释了它:Trigger an update of the UpdatePanel by a control that is in different ContentPlaceHolder)
这是一个在用户控件中公开按钮的完整工作示例,因此它可以充当父页面中的触发器和触发事件。使用子控件上的公共属性公开该按钮,然后所有事件处理程序都附加在父控件中。
<强> Default.aspx的强>
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<%@ Register Src="~/TestChildControl.ascx" TagName="Custom" TagPrefix="TestChildControl" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager runat="server" />
<div>
<asp:UpdatePanel runat="server" ID="updTest">
<Triggers>
<asp:AsyncPostBackTrigger ControlID="btnAddControl" EventName="Click" />
</Triggers>
<ContentTemplate>
<asp:Placeholder runat="server" ID="phControlContainer"></asp:Placeholder>
</ContentTemplate>
</asp:UpdatePanel>
<asp:Button runat="server" ID="btnAddControl" Text="Add Control" OnClick="btnAddControl_OnClick" />
</div>
</form>
</body>
</html>
<强> Default.aspx.cs 强>
请注意,必须以相同的顺序在页面加载上重新创建子控件,并使用相同的ID才能正确触发事件。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (ControlIDs != null)
{
foreach (string controlID in ControlIDs)
{
AddChildControl(controlID);
}
}
}
protected void btnAddControl_OnClick(object sender, EventArgs e)
{
var rand = new Random();
var controlID = string.Format("TestChildControl_{0}", rand.Next());
AddChildControl(controlID);
}
protected void AddChildControl(string controlID)
{
TestChildControl childControl = (TestChildControl)LoadControl("~/TestChildControl.ascx");
childControl.ID = controlID;
phControlContainer.Controls.Add(childControl);
childControl.RemoveControlButton.Click += btnRemoveControl_OnClick;
AsyncPostBackTrigger updateTrigger = new AsyncPostBackTrigger() { ControlID = childControl.RemoveControlButton.UniqueID, EventName = "click" };
updTest.Triggers.Add(updateTrigger);
SaveControlIDs();
}
private void SaveControlIDs()
{
ControlIDs = phControlContainer.Controls.Cast<Control>().Select(c => c.ID).ToList();
}
protected void btnRemoveControl_OnClick(object sender, EventArgs e)
{
var removeButton = sender as Button;
if (removeButton == null)
{
return;
}
var controlID = removeButton.CommandArgument;
var parentControl =
phControlContainer.Controls.Cast<TestChildControl>().FirstOrDefault(c => c.ID.Equals(controlID));
if (parentControl != null)
{
phControlContainer.Controls.Remove(parentControl);
}
SaveControlIDs();
}
protected IEnumerable<string> ControlIDs
{
get
{
var ids = ViewState["ControlIDs"] ?? new List<string>();
return (IEnumerable<string>) ids;
}
set { ViewState["ControlIDs"] = value; }
}
}
<强> TestChildControl.ascx 强>
<%@ Control Language="C#" AutoEventWireup="true" CodeFile="TestChildControl.ascx.cs" Inherits="TestChildControl" %>
<div>
This is a test control
</div>
<div>
<asp:Button runat="server" ID="btnRemoveControl" Text="Remove Control" />
</div>
<强> TestChildControl.ascx.cs 强>
请注意,这里我们将按钮公开为只读属性,以便我们可以为其分配事件处理程序并访问其成员。为方便起见,我将父控件ID指定为CommandArgument。
using System;
using System.Web.UI.WebControls;
public partial class TestChildControl : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
btnRemoveControl.CommandArgument = this.ID;
}
public Button RemoveControlButton
{
get { return btnRemoveControl; }
}
}