Nested repeater and datasource - asp.net

I have a repeater nested in an other repeater.
My question is: is it possible to generate other ItemTemplate components with datasource.
If yes, how can I do it ?
For example:
ItemTemplate1 of parentRepeater
A
B
C
ItemTemplate2 of parentRepeater
D
E
F
It means that ItemTemplate of childRepeater is changed for each ItemTemplate of parentRepeater.

<asp:Repeater runat="server" ID="repeater1"
onitemdatabound="Repeater1_ItemDataBound" >
<ItemTemplate>
<!--Outer repeater -->
<asp:repeater id="repeater2" runat="server">
<itemtemplate>
<!--Inner repeater repeater -->
</itemtemplate>
</asp:repeater>
</ItemTemplate>
</asp:Repeater>
`
Here is Back end code
protected void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
//it return current row (think in terms of nested loops)
DataRowView drv = (DataRowView)e.Item.DataItem;
// get value of that row
int postID = Convert.ToInt32(drv["PostID"]);
//do what ever you want to do
Repeater2.DataSource = //some data like you did in outer repeater
Repeater2.DataBind();
}
}

If your goal is to have them alternate back and forth between two templates, then use AlternateItemTemplate.
<asp:Repeater runat="server">
<ItemTemplate>
This came from ItemTemplate.
</ItemTemplate>
<AlternateItemTemplate>
This came from AlternateItemTemplate.
</AlternateItemTemplate>
</asp:Repeater>
This is commonly used when you want to vary the background color of each row in a table.

Related

How to find ItemIndex of outer repeater when user click radio button in the inner repeater

I have a nested repeater and need to findout the ItemIndex of the outer repeater when user click the radio button in the inner repeater.
I tried using rb.parent.parent and also rb.NamingContainer.NamingContainer but I got casting error.
I also searched different sites regarding similar problems but they were not a solution for mine.
Any comment is highly appreciated.
protected void rptrSubscriptionGroups_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
Repeater rptrSubscriptions = (Repeater)e.Item.FindControl("rptrSubscriptions");
if (rptrSubscriptions != null)
{
RepeaterItem item = e.Item;
if (e.Item.ItemType == (ListItemType.Item) || e.Item.ItemType == (ListItemType.AlternatingItem))
{
DataTable SubscriptionTbl = SubscriptionsBind(SelectedLanguageID, SelectedPlatformID, SelectedCurrencyID, SelectedGroupID, 1);
rptrSubscriptions.DataSource = SubscriptionTbl;
rptrSubscriptions.DataBind();
}
}
}
protected void HighlightSubscription(object source, EventArgs e)
{
RadioButton rb = source as RadioButton;
int CurrentrepeaterItemIndex = ((RepeaterItem)rb.NamingContainer).ItemIndex;
// save current row index in a hiddden field
hiddenSelectedSubscriptionRowIndex.Value = CurrentrepeaterItemIndex.ToString();
int ParentRepeaterItemIndex = ((RepeaterItem)rb.NamingContainer.NamingContainer).ItemIndex;
hiddenSelectedSubscriptionGroupRowIndex.Value = ParentRepeaterItemIndex.ToString();
}
<asp:Repeater ID="rptrSubscriptionGroups" runat="server" OnItemDataBound="rptrSubscriptionGroups_ItemDataBound" OnItemCommand="rptrSubscriptionGroups_ItemCommand">
<ItemTemplate>
<asp:Repeater ID="rptrSubscriptions" runat="server" OnItemDataBound="rptrSubscriptions_ItemDataBound" OnItemCommand="rptrSubscriptions_ItemCommand">
<ItemTemplate>
<asp:RadioButton ID="rbSubscription" runat="server" OnCheckedChanged="HighlightSubscription" AutoPostBack="true"/>
</ItemTemplate>
</asp:Repeater>
</ItemTemplate>
</asp:Repeater>
You said that you have tried with Parent.Parent but I think that you can do it with it :
int CurrentrepeaterItemIndex = ((RepeaterItem)rb.Parent.Parent.Parent).ItemIndex;
The First Parent is going one level up to the ItemTemplate :
<ItemTemplate>
<asp:RadioButton ID="rbSubscription" runat="server" OnCheckedChanged="HighlightSubscription" AutoPostBack="true"/>
The Second Parent is going again one level up to the inner Repeater :
<asp:Repeater ID="rptrSubscriptions" runat="server" OnItemDataBound="rptrSubscriptions_ItemDataBound" OnItemCommand="rptrSubscriptions_ItemCommand">
The Third Parent is going to the outer Repeater item and you can get the item index.
<asp:Repeater ID="rptrSubscriptionGroups" runat="server" OnItemDataBound="rptrSubscriptionGroups_ItemDataBound" OnItemCommand="rptrSubscriptionGroups_ItemCommand">
<ItemTemplate>

Nested Repeater HeaderTemplate issue

Hello i am using nested repeaters (3 levels) and wanted to add header to a second level repeater, so I could assign title for item group. The issue is, when I add header template to second level repeater, my code behind can't find third level repeater. Even if header template is empty the issue still persists. Does anyone have any suggestions?
<asp:Repeater runat="server" ID="rpt2nd" OnItemDataBound="rpt2nd_OnDataBound">
<HeaderTemplate></HeaderTemplate>
<ItemTemplate>
<asp:Repeater runat="server" ID="rpt3rd">
<ItemTemplate></ItemTemplate>
</asp:Repeater>
</ItemTemplate>
</asp:Repeater>
protected void rpt2nd_OnDataBound(object sender, RepeaterItemEventArgs e)
{
var rpt3rd= ((Repeater)e.Item.FindControl("rpt3rd"));
rpt3rd.DataSource = ((KeyValuePair<int, IEnumerable<CustomClass>>)e.Item.DataItem).Value;
rpt3rd.DataBind();
}
You need to add if(e.Item.ItemType != ListItemType.Item && e.Item.ItemType != ListItemType.AlternatingItem) return; to the top of the rpt2nd_OnDataBound (also, it should be renamed to rpt2nd_OnItemDataBound to avoid confusion).

how to find repeater inside another repeater

I want to find repeater inside the another repeater. But i m not able to find. My code is
<asp:Repeater ID="rep_test" runat="server">
<ItemTemplate>
<div id='h<%# DataBinder.Eval(Container, "ItemIndex") %>' class="header" onclick='ToggleDisplay(<%# DataBinder.Eval(Container, "ItemIndex") %>);'>
<%#DataBinder.Eval(Container.DataItem, "ID")%>
</div>
<div id='d<%# DataBinder.Eval(Container, "ItemIndex") %>' class="details">
<asp:Repeater ID="rep_hello" runat="server">
<ItemTemplate>
<%#DataBinder.Eval(Container.DataItem, "batchid")%><br />
<%#DataBinder.Eval(Container.DataItem, "ts")%><br />
</ItemTemplate>
</asp:Repeater>
<%-- <%#DataBinder.Eval(Container.DataItem, "batchid")%><br />
<%#DataBinder.Eval(Container.DataItem, "ts")%><br />--%>
</div>
</ItemTemplate>
</asp:Repeater>
If you put a repeater inside an item template of another repeater that means that every item of the main repeater (rep_test) will have a repeater inside it (rep_hello). So you actually need to find the repeater inside a repeaterItem. You can iterate trough all the nested repeaters like this:
foreach (RepeaterItem item in rep_test)
Repeater rptr = (Repeater)item.FindControl("rep_hello");
Example:
In ItemDataBound event handler:
protected void rep_test_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
(e.Item.FindControl("rep_hello") as Repeater).DataSource = YourOtherDataSource;
}
}
You can try using .FindControl(). In VB, it would be something like
Dim rpt as Repeater = rep_test.FindControl("rep_hello")
Usually when I see this kind of thing, you want to perform some event on all of the inner repeaters. What I usually do is handle this kind of thing inside the ItemDataBound event.
Add an OnItemDataBound attribute to your Repeater.
<asp:Repeater ID="rep_test" runat="server"
OnItemDataBound="rep_test_ItemDataBound">
Then in the back end, add a handler, with a FindControl call.
protected void rptBasket_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item ||
e.Item.ItemType == ListItemType.AlternatingItem)
{
Repeater innerRepeater = (Repeater)e.Item.FindControl("rep_hello");
// Now your have your repeater...do what you want with it.
}
}

Using Nested Repeaters With Stored Procedures

Hey I would like to use Nested Stored Procedures in ASP.NET 2.
The first stored procedure returns all Campains and second one returns all items in the campaigns.
I have my 2 repeaters set up, and now I am trying to pass a parameter from the parent repeater to child repeater stored procedure i.e campaign id....this proving tricky
In the code behind I wanted to try
public void Repeater1_ItemDataBound(Object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType ==
ListItemType.AlternatingItem || e.Item.ItemType == ListItemType.EditItem)
{
SqlDataSource2.SelectParameters["campaignId"].DefaultValue =
DataBinder.Eval(e.Item.DataItem, "campaignId").ToString();
}
}
But I dont know how to call this method or get it to load if I try this
<asp:Repeater ID="Repeater1" runat="server" DataSourceID="SqlDataSource1" OnDataBinding="Repeater1_ItemDataBound">
I get the error
CS0123: No overload for 'Repeater1_ItemDataBound' matches delegate 'System.EventHandler'
Any help would be greatly appreciated
EDIT : Changed mY Code Behind to
public void Repeater1_ItemDataBound(Object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType ==
ListItemType.AlternatingItem || e.Item.ItemType == ListItemType.EditItem)
{
Response.Write(DataBinder.Eval(e.Item.DataItem, "campaignId").ToString());
SqlDataSource2.SelectParameters["campaignId"].DefaultValue =
DataBinder.Eval(e.Item.DataItem, "campaignId").ToString();
SqlDataSource2.SelectParameters["statusId"].DefaultValue =
"1";
}
foreach (RepeaterItem repeaterItem in Repeater1.Items)
{
((Repeater)(repeaterItem.FindControl("Repeater2"))).DataBind();
}
}
But no joy its passing the correct campaign id to the stored procedure but this isnt displayed correctly on front end
any ideas ?
Instead of trying to attach the DataBinding event, you should be attaching the ItemDataBound event:
<asp:Repeater ID="Repeater1" runat="server"
DataSourceID="SqlDataSource1" OnItemDataBound="Repeater1_ItemDataBound">
The DataBinding event is for the whole repeater, the ItemDataBound will fire per item.
Microsoft publish an step by step guide to display hierarchical data using Nested Repeater Controls: Display Hierarchical Data
Remember that it is posible to return two datasets from a Store Procedure (An store procedure that ends with two SELECTs)
This is an example using EnterpriseLibrary
Try
Using cmd As DbCommand = db.GetStoredProcCommand("spYourStoreProcedure")
db.AddInParameter(cmd, "#customer", DbType.Int32, nCustomer)
Using ds = db.ExecuteDataSet(cmd)
ds.Tables(0).TableName = "Parent"
ds.Tables(1).TableName = "Child"
ds.Relations.Add("MyRelation", ds.Tables("Parent").Columns("customer"), ds.Tables("Child").Columns("customer"))
ParentRepeater.DataSource = ds.Tables("Parent")
ParentRepeater.DataBind()
End Using
End Using
Catch ex As Exception
' Manage your excepion
Exit Sub
End Try
This is a simple nested repeater:
<asp:Repeater ID="ParentRepeater" runat="server">
<HeaderTemplate>
<ul>
</HeaderTemplate>
<ItemTemplate>
<li>
<b><%# Container.DataItem("customer_name")%></b>
<asp:Repeater ID="repFuncionesXArea" runat="server" DataSource='<%# Container.DataItem.Row.GetChildRows("MyRelation") %>' >
<HeaderTemplate>
<ul>
</HeaderTemplate>
<ItemTemplate>
<li><%# Container.DataItem("customer_history")%></li>
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
</asp:Repeater>
</li>
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
</asp:Repeater>

Dynamically adding controls in ASP.NET Repeater

I find my self having a repeater control which is being databound to an xml document. My client is now requesting that the Textbox's which are being repeater can be either a Textbox or a Checkbox.
I cannot seem to find an easyway to essentially do the following:
if ((System.Xml.XmlNode)e.Item.DataItem.Attributes["type"] == "text")
<asp:TextBox runat="server" ID="txtField" Text='<%#((System.Xml.XmlNode)Container.DataItem).InnerText %>' CssClass="std"></asp:TextBox>
else
<asp:CheckBox runat="server" ID="txtField" Text='<%#((System.Xml.XmlNode)Container.DataItem).InnerText %>' CssClass="std"></asp:TextBox>
Is there a nice way I can extend my current implementaion without have to rewrite the logic. If I could inject the control via "OnItemDataBound" that would also be fine. But I cannot seem to make it work
In your repeater, drop a Panel, then create an event handler for the repeater's data binding event and programmatically create the TextBox or CheckBox and add it as a child control of the Panel. You should be able to get the DataItem from the event args to get information like your "type" attribute or values to feed your Text properties or css information, etc.
I would go with mspmsp's sugestion. Here is a quick and dirty code as an example of it:
Place this in your aspx:
<asp:Repeater ID="myRepeater" runat="server" OnItemCreated="myRepeater_ItemCreated">
<ItemTemplate>
<asp:PlaceHolder ID="myPlaceHolder1" runat="server"></asp:PlaceHolder>
<br />
</ItemTemplate>
</asp:Repeater>
And this in your codebehind:
dim plh as placeholder
dim uc as usercontrol
protected sub myRepeater_ItemCreated(object sender, RepeaterItemEventArgs e)
if TypeOf e Is ListItemType.Item Or TypeOf e Is ListItemType.AlternatingItem Then
plh = ctype(e.item.findcontrol("myPlaceHolder1"), Placeholder)
uc = Page.LoadControl("~/usercontrols/myUserControl.ascx")
plh.controls.add(uc)
end if
end sub
What about something similar to this in your markup in each the textbox and checkbox controls?
Visible=<%= Eval("type").tostring() == "text") %>
If there is needed to add controls based on data then there can be used this approach:
<asp:Repeater ID="ItemsRepeater" runat="server" OnItemDataBound="ItemRepeater_ItemDataBound">
<itemtemplate>
<div>
<asp:PlaceHolder ID="ItemControlPlaceholder" runat="server"></asp:PlaceHolder>
</div>
</itemtemplate>
</asp:Repeater>
protected void ItemRepeater_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
var placeholder = e.Item.FindControl("ItemControlPlaceholder") as PlaceHolder;
var col = (ItemData)e.Item.DataItem;
placeholder.Controls.Add(new HiddenField { Value = col.Name });
placeholder.Controls.Add(CreateControl(col));
}

Resources