So I'm trying to add and delete user controls on a page dynamically, by elaborating on an example I found online which shows how to add user controls dynamically. But I cannot seem to get the removal working properly. Procedure I follow is roughly.....
In the main page, when the add button is clicked, I create a user control and assign its
deleteBtnClkevent instance to methoddeleteBtn_Click(object sender, EventArgs e), which I pass methoducSimpleControl_deleteBtnClkfrom the main page code behindprotected void btnAddControl_Click(object sender, EventArgs e) { // Create instance of the UserControl SimpleControl usercontrols.SimpleControl ucSimpleControl = LoadControl("~/usercontrols/SimpleControl.ascx") as usercontrols.SimpleControl;... ... ...
ucSimpleControl.deleteBtnClk += new usercontrols.deleteBtn_Click(ucSimpleControl_deleteBtnClk);
I also do this is code behind method CreateUserControl(string controlID), which is called from the OnPreInit method...
protected override void OnPreInit(EventArgs e)
{
...
...
...
if ((control != null && control.ClientID ==
btnAddControl.ClientID) || createAgain)
{
...
...
...
CreateUserControl(controlID);
}
The OnClick method for the remove button in my user controls is set to deleteBtn_Click
protected void deleteBtn_Click(object sender, EventArgs e)
{
onDelBtnClk(e);
}
which calls the virtual method onDelBtnClk
protected virtual void onDelBtnClk(EventArgs e)
{
deleteBtnClk(this, e);
}
and passes this and the eventargs to the delegate, which on user control creation and rendering was assigned to code behind method ucSimpleControl_deleteBtnClk
void ucSimpleControl_deleteBtnClk(object sender, EventArgs e)
{
usercontrols.SimpleControl ucSimpleControl =
((usercontrols.SimpleControl)(sender));
ucSimpleControl.Parent.Controls.Remove(ucSimpleControl);
Session.Remove((ucSimpleControl.Num).ToString());
CreateUserControl(controlID);
}
In here I attempt to remove the user control by getting the parent control and invoking the Controls.Remove method with the sender user control as the argument. Then I remove the key-value pair associated with the user control from the Session, and finally call CreateUserControl again to render all user controls in Session. But the behavior is strange, only the most recently created user control is removed, not the one associated with the remove button clicked, and also after I remove one user control I cannot add more than the number of user controls that exist at that moment to the page. Like, for example, if there are 5 user controls on the page, and I remove one, then try to add more, I wont be able to add more than 5, though I should be able to add infinitely many. Here is the full source...
DisplayPage.aspx.cs
namespace UserControls4
{
public partial class DisplayPage : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void btnAddControl_Click(object sender, EventArgs e)
{
// Create instance of the UserControl SimpleControl
usercontrols.SimpleControl ucSimpleControl =
LoadControl("~/usercontrols/SimpleControl.ascx")
as usercontrols.SimpleControl;
// Set the Public Properties
ucSimpleControl.FirstName.Text = "Milind";
ucSimpleControl.LastName.Text = "Chavan";
//Create Event Handler for btnPost Click
ucSimpleControl.btnPostClk +=
new usercontrols.btnPost_Click(ucSimpleControl_btnPostClk);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
ucSimpleControl.deleteBtnClk +=
new usercontrols.deleteBtn_Click(ucSimpleControl_deleteBtnClk);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Add the SimpleControl to Placeholder
Placeholder1.Controls.Add(ucSimpleControl);
// Add the instance of the SimpleControl to Session Variable
Session.Add((Session.Count + 1).ToString(), ucSimpleControl);
// Set createAgain = true
createAgain = true;
}
void ucSimpleControl_btnPostClk(object sender, EventArgs e)
{
usercontrols.SimpleControl ucSimpleControl =
((usercontrols.SimpleControl)(sender));
lblUser.Text = "Welcome " + ucSimpleControl.FirstName.Text +
" " + ucSimpleControl.LastName.Text;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////
void ucSimpleControl_deleteBtnClk(object sender, EventArgs e)
{
usercontrols.SimpleControl ucSimpleControl =
((usercontrols.SimpleControl)(sender));
ucSimpleControl.Parent.Controls.Remove(ucSimpleControl);
Session.Remove((ucSimpleControl.Num).ToString());
CreateUserControl(controlID);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
// Declare 2 variable to handle user control after postback
const string controlID = "MyUserControl";
static bool createAgain = false;
protected Control GetPostBackControl(Page page)
{
Control control = null;
try
{
string ctrlName = page.Request.Params.Get("__EVENTTARGET");
if (ctrlName != null && ctrlName != String.Empty)
{
control = page.FindControl(ctrlName);
}
else
{
ContentPlaceHolder cph =
(ContentPlaceHolder)page.FindControl("Main");
for (int i = 0, len = page.Request.Form.Count; i < len; i++)
{
string[] ctl = page.Request.Form.AllKeys[i].Split('$');
if (ctl.Length > 3)
{
control = cph.FindControl(ctl[2])
as System.Web.UI.WebControls.Button;
}
if (control != null) break;
}
}
}
catch (Exception ex)
{
throw ex;
}
return control;
}
protected override void OnPreInit(EventArgs e)
{
base.OnPreInit(e);
Control control = GetPostBackControl(this.Page);
// Check if the postback is caused by the button
// Titled "Click to Create a Dynamic Control"
// OR
// createAgain field is true
// which means a call is made to the server while the
// user control is active
if ((control != null && control.ClientID ==
btnAddControl.ClientID) || createAgain)
{
//should be set before the CreateUserControl method
createAgain = true;
CreateUserControl(controlID);
}
}
protected void CreateUserControl(string controlID)
{
// createAgain field is set to true in the OnPreInit method
// when the 'Create User Control' button is clicked
// the createAgain field is used to check if the
// user control is on the page before the call
// if so create the control again and add it to the
// Control Hierarchy again
try
{
if (createAgain && Placeholder1 != null)
{
if (Session.Count > 0)
{
Placeholder1.Controls.Clear();
int simpleControlCount = 0;
for (int i = 0; i < Session.Count; i++)
{
switch (Session[i].ToString())
{
case "ASP.usercontrols_simplecontrol_ascx":
{
// Keep count of all SimpleControls
simpleControlCount++;
// Create instance of the UserControl SimpleControl
usercontrols.SimpleControl ucSimpleControl =
LoadControl("~/usercontrols/SimpleControl.ascx")
as usercontrols.SimpleControl;
// Set the Public Properties
ucSimpleControl.FirstName.Text =
((usercontrols.SimpleControl)(Session[i])).FirstName.Text;
ucSimpleControl.LastName.Text =
((usercontrols.SimpleControl)(Session[i])).LastName.Text;
ucSimpleControl.Num = simpleControlCount;
//Create Event Handler for btnPost Click
ucSimpleControl.btnPostClk +=
new usercontrols.btnPost_Click(ucSimpleControl_btnPostClk);
/////////////////////////////////////////////////////////////////////////////////////////////////////////
ucSimpleControl.deleteBtnClk +=
new usercontrols.deleteBtn_Click(ucSimpleControl_deleteBtnClk);
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//Add the SimpleControl to Placeholder
Placeholder1.Controls.Add(ucSimpleControl);
break;
}
}
}
}
}
}
catch (Exception ex)
{
throw ex;
}
}
}
}
DisplayPage.aspx
<head id="Head1" runat="server">
<title>This is example of how to add usercontrol dynamically</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Button ID="btnAddControl" runat="server"
Text="Click to add SimpleControl"
onclick="btnAddControl_Click" />
<br />
<asp:PlaceHolder runat="server"
ID="Placeholder1" ></asp:PlaceHolder>
<br />
<asp:Label ID="lblUser"
runat="server"></asp:Label>
</div>
</form>
</body>
</html>
SimpleControl.ascx.cs
namespace UserControls4.usercontrols
{
public delegate void btnPost_Click(object sender, System.EventArgs e);
public delegate void deleteBtn_Click(object sendre, System.EventArgs e);
public partial class SimpleControl : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
}
private int num;
#region Public Event
public event btnPost_Click btnPostClk;
public event deleteBtn_Click deleteBtnClk;
#endregion
#region Public Properties
public TextBox FirstName
{
get
{
return txtFirstName;
}
set
{
txtFirstName = value;
}
}
public TextBox LastName
{
get
{
return txtLastName;
}
set
{
txtLastName = value;
}
}
public int Num
{
get { return this.num; }
set { this.num = value; }
}
#endregion
#region Vitual Methods
protected virtual void OnbtnDelQtnMrClk(EventArgs e)
{
// Call btnPost_Click event delegate instance
btnPostClk(this, e);
}
/// ///////////////////////////////////////////////////////////////////////////////////////
protected virtual void onDelBtnClk(EventArgs e)
{
deleteBtnClk(this, e);
}
/// /////////////////////////////////////////////////////////////////////////////////////////
#endregion
protected void btnPost_Click(object sender, EventArgs e)
{
//Call Virtual Method
OnbtnDelQtnMrClk(e);
}
///////////////////////////////////////////////////////////////////////////////////////////
protected void deleteBtn_Click(object sender, EventArgs e)
{
onDelBtnClk(e);
}
}
}
SimpleControl.ascx
<table>
<tr>
<td><asp:Label ID="label1" runat="server"
Text="First Name" ></asp:Label></td>
<td> <asp:TextBox ID="txtFirstName"
runat="server"></asp:TextBox></td>
</tr>
<tr>
<td><asp:Label ID="label2" runat="server"
Text="Last Name" ></asp:Label></td>
<td> <asp:TextBox ID="txtLastName"
runat="server"></asp:TextBox></td>
</tr>
<tr>
<td><asp:Button ID="btnPost" runat="server"
Text="Send Info" OnClick="btnPost_Click" />
</td>
</tr>
</table>
<obout:SuperForm ID="UserControlSuperForm"
Width="630" Title="SuperForm"
AutoGenerateRows="false"
RunAt="server"
DefaultMode="Insert"
FolderStyle="styles/black_glass">
<Fields>
<obout:TemplateField HeaderText="SuperForm">
<EditItemTemplate>
<asp:TextBox ID="superFormTxt" runat="server"></asp:TextBox>
</EditItemTemplate>
</obout:TemplateField>
</Fields>
</obout:SuperForm>
<asp:Button ID="removeBtn" runat="server" Text="Remove" OnClick="deleteBtn_Click"/>