server controls nested in DataList

V

V. Jenks

What seems like a simple thing is apparently not so
straightforward?

I have a datalist.

Inside of that datalist is an <itemtemplate> secion which
contains other server controls such as a label, a
radiobuttonlist, etc.

I'm driving myself insane trying to figure out how to get
data in and out of those controls contained in the
datalist!

For example, I want to populate the radiobutton and label
being repeated for each row of data.

Also, the <itemtemplate> defines an imagebutton.

I want to be able (for each item) to choose something
from the radiobuttonlist and then click the imagebutton
to submit to another page.

I've found that I can use FindControl() in the
ItemCreated event handler for the DataList to *find* the
control itself, however, that isn't my problem.

My problem is in the OnClick event handler for the
imagebutton for each item, I'm unable to access the
radiobuttonlist selected item!

How is this done? What's the cleanest, simplest way to
get access and fire events from nested controls like this?

Thanks!
 
M

Martin Dechev

Hi, V. Jenks,

Maybe my replies to the subject "Controls in HeaderTemplate" by Yan Wang
could be helpful.

Basically this is the situation on the postback:

The handler for the ImageButton OnClick event is executed first - you set
some flag in a private field of your page class that this has happened.

Then the handler of the OnItemCreated event of the DataList gets executed.
Here you get gold of references to the controls you need to work with
later - store these in private fields of the class.

Then, after the viewstate is loaded (I choose to handle the PreRender event
of the DataList), check if there should be some processing (the flag set in
the ImageButton OnClick handler, that is). If yes - execute a method that
will do the actual processing.

Hope this helps
Martin
 
G

Guest

I'm not sure I follow you. Here is where I'm at:

The control:

<asp:datalist
id="CrossSellList"
onload="CrossSellList_Load"
onitemcreated="CrossSellList_ItemCreated"

onselectedindexchanged="CrossSellList_SelectedIndexChanged
"
repeatdirection="Vertical"
runat="server">
<itemtemplate>
<asp:radiobuttonlist

id="ProductOptionsList"

repeatdirection="Vertical"
cssclass="Normal"
runat="server"
/>

<asp:requiredfieldvalidator

controltovalidate="ProductOptionsList"

errormessage="You must choose a product option before
adding item to shopping cart!"

enableclientscript="True"
/>
<br />
<asp:imagebutton

id="AddToCartBttn"

onload="AddToCartBttn_Load"
runat="server"
/>
</td>
</tr>
</table>
</itemtemplate>
<selecteditemtemplate>
</selecteditemtemplate>
</asp:datalist>

In the code behind:

protected void CrossSellList_Load(object
sender, System.EventArgs e)
{
CrossSellList.DataSource =
ProductManager.GetCrossSellProducts();
CrossSellList.DataBind();
}

protected void AddToCartBttn_Load(object
sender, System.EventArgs e)
{
ImageButton bttn = (ImageButton)
sender;
bttn.ImageUrl = String.Format("/
{0}/images/buy_now.gif", this.WebRoot);
}

protected void CrossSellList_ItemCreated
(object sender, DataListItemEventArgs e)
{
ListItemType lit =
e.Item.ItemType;
if (lit == ListItemType.Header ||
lit ==
ListItemType.Footer ||
lit ==
ListItemType.Separator)
return;

Label titleLbl = (Label)
e.Item.FindControl("ProductAvailabilityLbl");
RadioButtonList prodOpList =
(RadioButtonList)e.Item.FindControl("ProductOptionsList");

if (!Page.IsPostBack)
{
IProduct product =
(IProduct)e.Item.DataItem;
IList prodOptions =
ProductManager.GetProductOptionsByProduct(product);

//populate product
options repeater
prodOpList.DataSource =
prodOptions;
prodOpList.DataTextField
= "Name";
prodOpList.DataValueField
= "ID";
prodOpList.DataBind();

if (prodOptions.Count > 0)
titleLbl.Text
= "Available in:";

Response.Write
(product.Name);
}
}


NOW - When each button is clicked, I want to access what
was chosen in each individual radiobuttonlist, and
redirect to a new page.
 
M

Martin Dechev

Hi,

The following is a working example. Sorry if I misleaded you, your situation
is quite simpler than the other one.

Anyway, little explanation of the code:

In the handler of the OnCommand event of the ImageButtons we loop through
the item collection of the DataList until FindControl("AddToCartBttn")
returns a control instance that equals the event source - the first
parameter of the handler, that is. Then we get reference to the
RadioButtonList which is in the current DataListItem and that's all.

listing <test.aspx>:

<%@ Page language="C#" inherits="test_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" xml:lang="en" lang="en">
<head>
<title>Test</title>
</head>
<body>
<form id="form1" method="post" runat="server">
<asp:datalist id="CrossSellList" runat="server"
repeatdirection="Vertical" runat="server">
<itemtemplate>
<asp:radiobuttonlist id="ProductOptionsList"
repeatdirection="Vertical" runat="server"
datasource='<%# DataBinder.Eval(Container.DataItem, "ARRAY")%>'/>
<br />
<asp:imagebutton id="AddToCartBttn"
oncommand="AddToCartBttn_Command" runat="server"
commandname='<%# DataBinder.Eval(Container.DataItem, "ID")%>'/>
</td>
</tr>
</table>
</itemtemplate>
</asp:datalist>
<br />
<br />
ID: <asp:literal id="LiteralID" runat="server"/><br />
Selected: <asp:literal id="LiteralSelected" runat="server"/>
</form>
</body>
</html>

listing <test_aspx.cs>:

using System;

public class test_aspx : System.Web.UI.Page
{
protected System.Web.UI.WebControls.DataList CrossSellList;
protected System.Web.UI.WebControls.Literal LiteralID, LiteralSelected;

protected void Page_Load(object s, EventArgs e)
{
if(!IsPostBack)
{
System.Data.DataTable dt =
new System.Data.DataTable();
System.Data.DataRow dr;
dt.Columns.Add("ID", typeof(string));
dt.Columns.Add("ARRAY", typeof(string[]));
dr = dt.NewRow();
dr[0] = "1";
dr[1] = new string[]
{"Option 1", "Option 2", "Option 3"};
dt.Rows.Add(dr);
dr = dt.NewRow();
dr[0] = "2";
dr[1] = new string[]
{"Value 1", "Value 2", "Value 3"};
dt.Rows.Add(dr);
CrossSellList.DataSource = dt.DefaultView;
CrossSellList.DataBind();
}
}

protected void AddToCartBttn_Command(object s,
System.Web.UI.WebControls.CommandEventArgs e)
{
foreach(System.Web.UI.WebControls.DataListItem item
in CrossSellList.Items)
{
if(item.ItemType == System.Web.UI.WebControls.ListItemType.Item ||
item.ItemType == System.Web.UI.WebControls.ListItemType.AlternatingItem)
{
System.Web.UI.WebControls.ImageButton AddToCartBttn =
item.FindControl("AddToCartBttn") as
System.Web.UI.WebControls.ImageButton;
if(AddToCartBttn != null && AddToCartBttn.CommandName == e.CommandName)
{
System.Web.UI.WebControls.RadioButtonList _ProductOptionsList =
item.FindControl("ProductOptionsList") as
System.Web.UI.WebControls.RadioButtonList;
LiteralID.Text = e.CommandName;
LiteralSelected.Text = string.Format(
@"Index: {0};Value: {1};Text: {2}",
_ProductOptionsList.SelectedIndex,
_ProductOptionsList.SelectedValue,
_ProductOptionsList.SelectedItem.Text);
}
}
}
}
}

Hope this helps
Martin
 
M

Martin Dechev

Sorry, I posted an earlier version, that can be simplificated a bit. Replace
this:
System.Web.UI.WebControls.ImageButton AddToCartBttn =
item.FindControl("AddToCartBttn") as
System.Web.UI.WebControls.ImageButton;
if(AddToCartBttn != null && AddToCartBttn.CommandName == e.CommandName)
{

with this:

object AddToCartBttn = item.FindControl("AddToCartBttn");
if(AddToCartBttn != null && AddToCartBttn.Equals(s)) {

In the AddToCartBttn_Command handler.

Greetings
Martin
Martin Dechev said:
Hi,

The following is a working example. Sorry if I misleaded you, your situation
is quite simpler than the other one.

Anyway, little explanation of the code:

In the handler of the OnCommand event of the ImageButtons we loop through
the item collection of the DataList until FindControl("AddToCartBttn")
returns a control instance that equals the event source - the first
parameter of the handler, that is. Then we get reference to the
RadioButtonList which is in the current DataListItem and that's all.

listing <test.aspx>:

<%@ Page language="C#" inherits="test_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" xml:lang="en" lang="en">
<head>
<title>Test</title>
</head>
<body>
<form id="form1" method="post" runat="server">
<asp:datalist id="CrossSellList" runat="server"
repeatdirection="Vertical" runat="server">
<itemtemplate>
<asp:radiobuttonlist id="ProductOptionsList"
repeatdirection="Vertical" runat="server"
datasource='<%# DataBinder.Eval(Container.DataItem, "ARRAY")%>'/>
<br />
<asp:imagebutton id="AddToCartBttn"
oncommand="AddToCartBttn_Command" runat="server"
commandname='<%# DataBinder.Eval(Container.DataItem, "ID")%>'/>
</td>
</tr>
</table>
</itemtemplate>
</asp:datalist>
<br />
<br />
ID: <asp:literal id="LiteralID" runat="server"/><br />
Selected: <asp:literal id="LiteralSelected" runat="server"/>
</form>
</body>
</html>

listing <test_aspx.cs>:

using System;

public class test_aspx : System.Web.UI.Page
{
protected System.Web.UI.WebControls.DataList CrossSellList;
protected System.Web.UI.WebControls.Literal LiteralID, LiteralSelected;

protected void Page_Load(object s, EventArgs e)
{
if(!IsPostBack)
{
System.Data.DataTable dt =
new System.Data.DataTable();
System.Data.DataRow dr;
dt.Columns.Add("ID", typeof(string));
dt.Columns.Add("ARRAY", typeof(string[]));
dr = dt.NewRow();
dr[0] = "1";
dr[1] = new string[]
{"Option 1", "Option 2", "Option 3"};
dt.Rows.Add(dr);
dr = dt.NewRow();
dr[0] = "2";
dr[1] = new string[]
{"Value 1", "Value 2", "Value 3"};
dt.Rows.Add(dr);
CrossSellList.DataSource = dt.DefaultView;
CrossSellList.DataBind();
}
}

protected void AddToCartBttn_Command(object s,
System.Web.UI.WebControls.CommandEventArgs e)
{
foreach(System.Web.UI.WebControls.DataListItem item
in CrossSellList.Items)
{
if(item.ItemType == System.Web.UI.WebControls.ListItemType.Item ||
item.ItemType == System.Web.UI.WebControls.ListItemType.AlternatingItem)
{
System.Web.UI.WebControls.ImageButton AddToCartBttn =
item.FindControl("AddToCartBttn") as
System.Web.UI.WebControls.ImageButton;
if(AddToCartBttn != null && AddToCartBttn.CommandName == e.CommandName)
{
System.Web.UI.WebControls.RadioButtonList _ProductOptionsList =
item.FindControl("ProductOptionsList") as
System.Web.UI.WebControls.RadioButtonList;
LiteralID.Text = e.CommandName;
LiteralSelected.Text = string.Format(
@"Index: {0};Value: {1};Text: {2}",
_ProductOptionsList.SelectedIndex,
_ProductOptionsList.SelectedValue,
_ProductOptionsList.SelectedItem.Text);
}
}
}
}
}

Hope this helps
Martin
I'm not sure I follow you. Here is where I'm at:

The control:

<asp:datalist
id="CrossSellList"
onload="CrossSellList_Load"
onitemcreated="CrossSellList_ItemCreated"

onselectedindexchanged="CrossSellList_SelectedIndexChanged
"
repeatdirection="Vertical"
runat="server">
<itemtemplate>
<asp:radiobuttonlist

id="ProductOptionsList"

repeatdirection="Vertical"
cssclass="Normal"
runat="server"
/>

<asp:requiredfieldvalidator

controltovalidate="ProductOptionsList"

errormessage="You must choose a product option before
adding item to shopping cart!"

enableclientscript="True"
/>
<br />
<asp:imagebutton

id="AddToCartBttn"

onload="AddToCartBttn_Load"
runat="server"
/>
</td>
</tr>
</table>
</itemtemplate>
<selecteditemtemplate>
</selecteditemtemplate>
</asp:datalist>

In the code behind:

protected void CrossSellList_Load(object
sender, System.EventArgs e)
{
CrossSellList.DataSource =
ProductManager.GetCrossSellProducts();
CrossSellList.DataBind();
}

protected void AddToCartBttn_Load(object
sender, System.EventArgs e)
{
ImageButton bttn = (ImageButton)
sender;
bttn.ImageUrl = String.Format("/
{0}/images/buy_now.gif", this.WebRoot);
}

protected void CrossSellList_ItemCreated
(object sender, DataListItemEventArgs e)
{
ListItemType lit =
e.Item.ItemType;
if (lit == ListItemType.Header ||
lit ==
ListItemType.Footer ||
lit ==
ListItemType.Separator)
return;

Label titleLbl = (Label)
e.Item.FindControl("ProductAvailabilityLbl");
RadioButtonList prodOpList =
(RadioButtonList)e.Item.FindControl("ProductOptionsList");

if (!Page.IsPostBack)
{
IProduct product =
(IProduct)e.Item.DataItem;
IList prodOptions =
ProductManager.GetProductOptionsByProduct(product);

//populate product
options repeater
prodOpList.DataSource =
prodOptions;
prodOpList.DataTextField
= "Name";
prodOpList.DataValueField
= "ID";
prodOpList.DataBind();

if (prodOptions.Count > 0)
titleLbl.Text
= "Available in:";

Response.Write
(product.Name);
}
}


NOW - When each button is clicked, I want to access what
was chosen in each individual radiobuttonlist, and
redirect to a new page.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,754
Messages
2,569,527
Members
44,998
Latest member
MarissaEub

Latest Threads

Top