Number of items in result in ASP repeater with Sitecore - asp.net

I'm working with Sitecore ascx file, and got something like this:
<asp:Repeater ID="NavRepeater" runat="server">
<ItemTemplate>
<div class="item">
<img src="<%# ((Sitecore.Data.Items.Item)Container.DataItem).Fields["Image Url"] %>" width="360" height="420" alt="">
</div>
</ItemTemplate>
<SeparatorTemplate></SeparatorTemplate>
</asp:Repeater>
Can't figure out, how to get total number of elements from Sitecore.Data.Items.Item.
I was also wondering how to retrieve given item in collection - like item no 2 ?

It's on the data source of your repeater in C#:
So if your C# is:
NavRepeater.DataSource = someData;
Then the length is someData.Length or someData.Count() based on its type.
For getting a specific item at a location:
Item second = someData[1]; // per 0-indexing
Or based on type, can also be:
Item second = someData.ElementAt(1) // per 0-indexing

You can have something like :
<asp:Repeater ID="NavRepeater" runat="server" OnItemDataBound="rptGallery_ItemDataBound">
<ItemTemplate>
<div class="item">
<sc:fieldrenderer id="fldGalleryItemImageThumbnail" runat="server" fieldname="ImageUrl" disablewebediting="true" />
</div>
</ItemTemplate>
<SeparatorTemplate></SeparatorTemplate>
</asp:Repeater>
On Page_Load you will have:
protected void Page_Load(object sender, EventArgs e)
{
rptGallery.DataSource = listofitemyyouwanttoshow;
rptGallery.DataBind();
}
On rptGallery_ItemDataBound event you will have:
protected void rptGallery_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
Item item = (Item)e.Item.DataItem;
//you can check index here of item
if (item != null)
{
var fldGalleryItemImageThumbnail = e.Item.FindControl("fldGalleryItemImageThumbnail") as FieldRenderer;
if (fldGalleryItemImageThumbnail != null)
{
fldGalleryItemImageThumbnail.DataSource = item.ID.ToString();
fldGalleryItemImageThumbnail.Parameters = String.Format("width={0}", 360);
}
}
}
}
}
I hope it helps you .

You would get these from the enumerable that you are binding you repeater to.

Related

Getting the id of a repeater field in asp.net

I am faceing a problem. I have a image view that contains a repeater. What i want to do is when the last image is shown the site needs to be redirected but i dont know how to get the current field that is shown. I was thinking that i could make a variable that holds the current id and compare it every time a new image is shown. And if the new images id is lower than the one in the other variable it has to redirect.
At the moment i dont really have any code to post because i really don know how to solve this. Hope some of you can help.
This is the code for the repeater on the html site
<div id="imgBack" runat="server" class="row" style="background-color: black;">
<div class="col-lg-12">
<div class="container">
<div class="fotorama" data-arrows="false" data-maxheight="750" data-allowfullscreen="native" data-loop="false" data-ratio="1024/750" data-nav="false" data-autoplay="5000" data-click="false" data-swipe="false" data-stopautoplayontouch="false" data-transition="crossfade" data-shuffle="true" data-fit="contain">
<asp:Repeater ID="repImgs" runat="server" OnItemDataBound="repImgs_ItemDataBound">
<ItemTemplate>
<asp:Image ID="imgs" ImageUrl='<%# string.Format("~/Images/{0}", Eval("FileName")) %>' runat="server" />
</ItemTemplate>
</asp:Repeater>
</div>
</div>
</div>
</div>
And here is what i got on the back end so far
protected void repImgs_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
if (e.Item.ItemIndex == repImgs.Items.Count - 1)
{
Response.Redirect("FinishedSession.aspx");
}
}
}
To get the last item in your repeater you could use ItemDataBound
protected void MyRepeater_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
if (e.Item.ItemIndex == MyRepeater.Items.Count - 1)
{
// Do something
}
}
}

Difficulty in displaying data using repeater

I am trying to display shopping categories with its sub categories and sub-sub categories using repeater.. Data is binding but it is not being displayed.. Can anyone help why?
here's my code:
.aspx file
<asp:Repeater ID="CategoryRepeater" runat="server" OnItemDataBound="CategoryRepeater_OnItemDataBound">
<ItemTemplate>
<a href='Clothing.aspx?CategoryId=<%#Eval("CategoryId") %>'<%#Eval("CategoryName") %>></a><br />
<asp:Repeater ID="SubCategoryRepeater" runat="server" OnItemDataBound="SubCategoryRepeater_OnItemDataBound">
<ItemTemplate>
<a href='Clothing.aspx?CategoryId=<%#Eval("CategoryId") %>&SubCategoryId=<%#Eval("SubCategoryId") %>'<%#Eval("SubCategoryName") %>></a><br />
<asp:Repeater ID="SubSubCategoryRepeater" runat="server">
<ItemTemplate>
<a href='Clothing.aspx?CategoryId=<%#Eval("CategoryId") %>&SubCategoryId=<%#Eval("SubCategoryId") %>&SubSubCategoryId=<%#Eval("SubSubCategoryId") %>'<%#Eval("SubSubCategoryName") %>></a><br />
</ItemTemplate>
</asp:Repeater>
</ItemTemplate>
</asp:Repeater>
</ItemTemplate>
</asp:Repeater>
C# Code:
protected void CategoryRepeater_OnItemDataBound(object sender, RepeaterItemEventArgs e)
{
if ((e.Item.ItemType == ListItemType.Item)||(e.Item.ItemType == ListItemType.AlternatingItem))
{
DataRowView dataItem = e.Item.DataItem as DataRowView;
int categoryId = Convert.ToInt32(dataItem["CategoryId"]);
Repeater rp = (Repeater)e.Item.FindControl("SubCategoryRepeater");
ds = us.SelectSubCategories(categoryId);
rp.DataSource = ds;
rp.DataBind();
}
}
protected void SubCategoryRepeater_OnItemDataBound(object sender, RepeaterItemEventArgs e)
{
if ((e.Item.ItemType == ListItemType.Item)||(e.Item.ItemType == ListItemType.AlternatingItem))
{
DataRowView dataItem = e.Item.DataItem as DataRowView;
int SubCategoryId = Convert.ToInt32(dataItem["SubCategoryId"]);
Repeater rp1 = (Repeater)e.Item.FindControl("SubSubCategoryRepeater");
ds1 = us.SelectSubSubCategories(SubCategoryId);
rp1.DataSource = ds1;
rp1.DataBind();
}
}
Check your source code to make sure nothing is being output to the page. I think you just have the category name being rendered inside the anchor tag.
Here is the same code with the evals simplified to see what is going on
<a href='Clothing.aspx?CategoryId={catid}'{name}></a>
Should be:
<a href='Clothing.aspx?CategoryId={catid}'>{name}</a>
or
<a href='Clothing.aspx?CategoryId=<%#Eval("CategoryId") %>'><%#Eval("CategoryName") %></a>
Same mistake was done in all three locations.
I think everything is correct from the code, but your output is wrong.
You are doing this:
<a href='Clothing.aspx?CategoryId=<%#Eval("CategoryId") %>&SubCategoryId=<%#Eval("SubCategoryId") %>'<%#Eval("SubCategoryName") %>></a><br />
But it needs to be
<a href='Clothing.aspx?CategoryId=<%#Eval("CategoryId") %>&SubCategoryId=<%#Eval("SubCategoryId") %>'><%#Eval("SubCategoryName") %></a><br />
Noticed I moved the '>' back behind <%# Eval("SubCategoryName")%>

Repeater inside repeater not binding properly

I have a repeater inside another. Like so :
<asp:Repeater ID="CategoryRepeater" runat="server" OnItemDataBound="ItemBound">
<ItemTemplate>
<div class="groupbox">
<fieldset>
<legend><%# Container.DataItem %></legend>
<table>
<asp:Repeater ID="ItemRepeater" runat="server">
<ItemTemplate>
<tr>
<td>
<asp:CheckBox id="chkItem" runat="server" Text='<%# Eval("Text")%>' />
<asp:Button ID="btnXRefs" Text="x-refs" runat="server" CssClass="xRefButton" OnClick="btnSelectXRefs_Click" />
</td>
</tr>
</ItemTemplate>
</asp:Repeater>
</table>
</fieldset>
</div>
</ItemTemplate>
</asp:Repeater>
CODE BEHIND :
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
using (var db = new DbContext())
{
CategoryRepeater.DataSource = db.Categories.OrderBy(x => x.Heading).Select(x => x.Heading).Distinct();
CategoryRepeater.DataBind();
}
}
}
protected void ItemBound(object sender, RepeaterItemEventArgs args)
{
if (args.Item.ItemType == ListItemType.Item)
{
Repeater childRepeater = (Repeater)args.Item.FindControl("ItemRepeater");
var item = args.Item as RepeaterItem;
using (var db = new DbContext())
{
childRepeater.DataSource = db.Categories.Where(x => x.Heading == item.DataItem).OrderBy(x => x.Text);
childRepeater.DataBind();
}
}
}
My goal is to first make many groupboxes using the top level, then bind items into each one. So I end up with many small stacked lists of checkboxes.
Problem is, all the top level boxes appear, yet only the first one contains checkbox items, ie. only the first one is bound internally, and the ItemBound method is only called once for the first one.
Any ideas why?
This line
if (args.Item.ItemType == ListItemType.Item)
Should be like this
if(args.Item.ItemType = ListItemType.Item ||
args.Item.ItemType == ListItemType.AlternatingItem)

Injecting table row inside repeater item

I am trying to inject inside repeaters items, the problem is that the row is generated in a wrong location.
If you try this simple example, you will see that the rown is generated under label '2' as it should be generated under label '1'.
Why does it happen? And how to fix that?
protected void Page_Load(object sender, EventArgs e)
{
int [] array = {1,2,3,4,5};
rpt.DataSource = array;
rpt.DataBind();
}
protected string _extraRowHtml;
protected void rpt_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item ||
e.Item.ItemType == ListItemType.AlternatingItem)
{
int tmp = ((int)e.Item.DataItem);
_extraRowHtml = tmp == 1 ? "<tr><td class=\"topicsRow\" colspan=\"100%\"> Topics </td></tr>" : string.Empty; ;
}
}
<asp:Repeater ID="rpt" runat="server" onitemdatabound="rpt_ItemDataBound">
<HeaderTemplate>
<table cellpadding="0px" cellspacing="0">
</HeaderTemplate>
<ItemTemplate>
<tr style="height:50px">
<td>
<asp:HyperLink ID="lnkTitle" runat="server" Text='<%# Container.DataItem%>'/>
</td>
</tr>
<%# _extraRowHtml %>
</ItemTemplate>
<FooterTempl
</table>
</FooterTemplate>
</asp:Repeater>
Personally I think a better way of doing is is to replace:
<%# _extraRowHtml %>
with
<%# GetExtraRow(Container.DataItem) %>
then in your code behind implement:
protected string GetExtraRow(object Data)
{
int tmp = (int) Data:
return _tmp == 1 ?
"<tr><td class=\"topicsRow\" colspan=\"100%\"> Topics </td></tr>" :
string.Empty;
}
Then and get rid of the rpt_ItemDataBound function (and the onItemDataBound).
Doing things this way is going to be prone to error, as using a variable in this manner is not something that you are going to have full control over.
What I would do is add something like the following to the template.
<asp:literal id="litExtraRow" runat="server" mode="Passthrough" />
Then in your codebehind on the item databound event
if (((int)e.Item.DataItem) == 1)
{
((Literal)e.Item.FindControl("litExtraRow")).Text = "Your HTML Here";
}
Something like this should be a bit more reliable.
The reason you are having issues is that the template is evaluated with the values as they are as "ItemDataBound" has been called, and row 1, the value is string.Empty, and then for the second row, you updated it after item 1 was databound.

Loop in code block on click argument

Basically what i am trying to do is display a list of categories. And if the admin is logged in
i want to show some buttons next to each category. For example a button to delete it. The problem is that i dont know how to pass a parameter to the function that does the action.
Like i specify that on button click the function 'DeleteCat' must be called but if i cant pass the ID of the category to be deleted this wont work.
I know this can be done with commands and a repeater, but its not an option, i cant use a repeater.
So apparanly this is what i am aiming for:
But of course it does not work.
<%For Each Cat In Category.Children%>
<p class="SubCategory">
<%=Cat.Name%>
<%If User.Identity.Name = "Admin" Then%>
<asp:LinkButton ID="LinkButton6" runat="server" OnClick="AddItem" Text="A+" CommandArgument=<%=Cat.ID %> />
<%End If%>
</p>
<%Next %>
Your event handler AddItem should be able to evaluate the sender of the event and the CommandEventArgs
void AddItem(Object sender, EventArgs e)
{
int result;
bool returnValue;
Button clickedButton = (Button)sender;
returnValue = Int32.TryParse(clickedButton.CommandArgument, result);
// then other stuff happens ...
}
See detailed example here.
edit
Completed code sample as suggested by Brandon.
Alternative solution, using a CheckBoxList
...
<script language="C#" runat="server">
void Page_Load(Object Sender, EventArgs e)
{
if (!IsPostBack)
{
// bind data to controls
this.itemRepeater.DataSource = Category.Children;
this.adminList.DataSource = Category.Children;
this.itemRepeater.DataBind();
this.adminList.DataBind();
}
// set visibility according to user
this.itemRepeater.Visible = (User.Identity.Name != "Admin");
this.adminList.Visible = (User.Identity.Name == "Admin");
this.adminButton.Visible = (User.Identity.Name == "Admin");
}
protected void AddItem(object sender, EventArgs e)
{
foreach(ListItem currentitem in this.adminList.Items)
{
if(currentitem.Selected)
{
// do something with the selected value
int i;
bool isparsed = Int32.TryParse(currentitem.value, i);
}
}
}
</script>
</head>
<body>
<form id="mainForm" runat="server">
<asp:Repeater ID="itemRepeater" runat="server">
<ItemTemplate>
<p><%# DataBinder.Eval(Container.DataItem, "value") %></p>
</ItemTemplate>
</asp:Repeater>
<asp:CheckBoxList ID="adminList" runat="server" />
<br />
<asp:Button ID="adminButton" OnClick="AddItem" runat="server" Text="Add seleted Items" />
</form>
</body>

Resources