Reputation: 43
I have been searching around and I am lost on how to do what I am attempting to do.
I am trying to create a form where the first column is a list of names, and the next column is all dropdown lists. The idea is that for each name the user will pic a value. Each name may require two, or three or more values. I want to create a dynamic form where a user can click add in the row and another dropdown list appears.
Ex. "Name" | Add Button | DropDown
then when I click add...
"Name" | Add Button | DropDown | DropDown
and have it keep going.
I am able to create the form and I have it working creating the dropdown lists. The problem is that I am adding the controls on the ItemCommand of a repeater, so they must be recreated every time. Because of this I cannot find a way to keep the values selected in each dropdown, when I have to recreate them.
Typically no more than two dropdowns are required but there are a few cases where three is needed, and it could arise for more. I would like to keep this dynamic as possible.
I know that if I added the dropdown's in the page Init they would be persisted on the postback, but at least in my design the user has to click add to get another drop down.
Is there a way to capture the data from these dropdowns then reload them every time? Or a better way to achieve this functionality?
Thank You for your help.
Here is some of the asp and code behind that I am using. This is functioning as I wish, but I don't know how to keep the data on a postback, as all of the dropdown lists I add are lost.
ASP:
<table>
<asp:Repeater ID="repChemicals" runat="server" OnItemCommand="repChemicals_OnItemCommand">
<ItemTemplate>
<tr>
<td>
<asp:HiddenField ID="hfNumber" runat="server" />
<%# Eval("ChemicalName") %>
</td>
<td>
<asp:Button runat="server" ID="btnAdd" Text="Add" CommandArgument="ADD" />
</td>
<td>
<div id="divContainer" runat="server">
<asp:DropDownList runat="server" Width="60px" ID="ddlTest"></asp:DropDownList>
</div>
</td>
</tr>
</ItemTemplate>
</asp:Repeater>
</table>
C#:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
List<Chem> Chemicals = new List<Chem>();
Random rnd = new Random();
for (int z = 0; z <= 10; z++)
{
List<string> t = new List<string>();
Chem a = new Chem()
{
ChemicalName = "Chemical" + z.ToString()
};
Chemicals.Add(a);
}
repChemicals.DataSource = Chemicals;
repChemicals.DataBind();
}
}
public void repChemicals_OnItemCommand(object sender, RepeaterCommandEventArgs e)
{
int number = 0;
foreach (RepeaterItem i in repChemicals.Items)
{
HiddenField hf = (HiddenField)repChemicals.Items[i.ItemIndex].FindControl("hfNumber");
if (i.ItemIndex == e.Item.ItemIndex)
{
if (!string.IsNullOrWhiteSpace(hf.Value))
{
number = Convert.ToInt16(hf.Value) + 1;
}
else
{
number = 1;
}
hf.Value = number.ToString();
}
else
{
if (!string.IsNullOrWhiteSpace(hf.Value))
{
number = Convert.ToInt16(hf.Value);
}
else
{
number = 0;
}
}
for (int x = 0; x < number; x++)
{
DropDownList ddl = new DropDownList();
ddl.Style.Add("width", "60px");
ddl.ID = "ddl" + i.ToString() + x.ToString();
ddl.Style.Add("Margin-right", "3px");
ddl.Attributes.Add("runat", "server");
ddl.DataSource = DataSource();
ddl.DataBind();
Control c = repChemicals.Items[i.ItemIndex].FindControl("divContainer");
c.Controls.Add(ddl);
}
}
Some of the loops are for creating test data. Basically I am storing a number of dynamic controls on each row in a hiddenfield. Then on the item command I loop through all of the rows and recreate all of the previously existing ddl's, and add one to the row that teh command came from.
Upvotes: 3
Views: 2512
Reputation: 955
This isn't exactly answering your question, but it accomplishes your ultimate goal in a less complex way and one that takes advantage of built in ASP.NET controls so maintaining state between postbacks is taken care of for you.
It utilizes jQuery, jQuery UI and a DropDownChecklist plugin.
ASPX
<!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 runat="server">
<title></title>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.7.2.min.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.21/jquery-ui.min.js"></script>
<script type="text/javascript" src="js/ui.dropdownchecklist.js"></script>
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.21/themes/base/jquery-ui.css"/>
</head>
<body>
<form id="form1" runat="server">
<div>
<table>
<asp:Repeater ID="repChemicals" runat="server">
<ItemTemplate>
<tr>
<td>
<%# Container.DataItem %>
</td>
<td>
<div id="divContainer" runat="server">
<asp:ListBox ID="lstAttributes" SelectionMode="Multiple" runat="server"></asp:ListBox>
</div>
</td>
</tr>
</ItemTemplate>
</asp:Repeater>
</table>
<asp:Button ID="btnPostback" Text="Postback" runat="server"/>
</div>
</form>
</body>
</html>
C#
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace PersonAttributes
{
public partial class People : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
repChemicals.ItemCreated += RepChemicalsOnItemCreated;
var chemicals = new[] {"Hydrogen", "Helium", "Lithium", "Beryllium", "Boron"};
if(!IsPostBack)
{
repChemicals.DataSource = chemicals;
repChemicals.DataBind();
}
var dropDownChecklist = "$(document).ready(function () { $('select').dropdownchecklist(); });";
ScriptManager.RegisterStartupScript(this,GetType(),"initDropDownChecklist",dropDownChecklist,true);
}
private void RepChemicalsOnItemCreated(object sender, RepeaterItemEventArgs repeaterItemEventArgs)
{
var lst = repeaterItemEventArgs.Item.FindControl("lstAttributes") as ListBox;
if (lst == null)
return;
lst.DataSource = new[] {"Option 1", "Option 2", "Option 3"};
}
}
}
See it in action at CodeRun.
Upvotes: 1