C# Repeater - Show AlternatingItem template every 3rd item - c#

I have my repeater set up all working fine, but there's a few tweaks i need to make to every third item. my code is below
<asp:Repeater ID="rptItems" runat="server" onitemdatabound="rptItems_ItemDataBound">
<ItemTemplate>
content / html / eval
</ItemTemplate>
<AlternatingItemTemplate>
content / html / eval
</AlternatingItemTemplate>
</asp:Repeater>
then in my onitemdatabound set up
protected void rptItems_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
// check to see if this is the page to show the form on
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
if (e.Item.ItemType == ListItemType.AlternatingItem)
{
e.Item.Visible = ((e.Item.Parent as Repeater).Items.Count % 3 == 0);
}
}
}
but this doesnt seem to work, it just hides one of the items, any help would be great.

You need to use item index not Count. Count is static value.
May be something like that:
e.Item.Visible = (e.Item.Index % 3 == 0);

use the RepeaterItem.ItemIndex instead of Items.Count
e.Item.ItemIndex % 3 == 0
so:
e.Item.Visible = e.Item.ItemType == ListItemType.AlternatingItem &&
e.Item.ItemIndex % 3 == 0
read more on MSDN
remove the Alternating item to do the modifications on every 3th item exclusively.
<asp:Repeater ID="rptItems" runat="server" onitemdatabound="rptItems_ItemDataBound">
<ItemTemplate>
content / html / eval
</ItemTemplate>
</asp:Repeater>
And your behind code would be:
e.Item.Visible = e.Item.ItemIndex % 3 == 0

Related

How to Get Count of Items in Repeater inside ItemDataBound

I have one Repeater
<asp:Repeater runat="server" ID="rptID" OnItemDataBound="repID_ItemDataBound">
<ItemTemplate>
<a href='example.com/somepage.aspx' id="myLink">
<%# Eval("MyVal")%>
</a>
</ItemTemplate>
</asp:Repeater>
In Code Behind I need to add one css class for this <a> tag when in repeater is one
Item
protected void repID_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item ||
e.Item.ItemType == ListItemType.AlternatingItem)
{
//how to set this class only then count of items is equal with 1
((HtmlGenericControl)e.Item.FindControl("myLink")).Attributes
.Add("class", "Count1");
}
}
This will give you the count of your datasource items:
if (((IEnumerable)rptID.DataSource).Cast<object>().Count() == 1)
{
((HtmlGenericControl)e.Item.FindControl("myLink")).Attributes
.Add("class", "Count1");
}
Counting the IEnumerable was borrowed from this thread: Calculating Count for IEnumerable (Non Generic)

add strong element in ItemDataBound around span

Is there a way in the code-behind to add a strong element around my asp:Label in the ItemDataBound event (between the li and asp:Label elements) when rendered?
the markup
<asp:Repeater ID="Repeater1" runat="server" DataSourceID="SqlDataSource1">
<ItemTemplate>
<li>
<asp:Label ID="Label1" runat="server" Text='<%# Bind("ProductName") %>'></asp:Label>
</li>
</ItemTemplate>
</asp:Repeater>
csharp code behind, this is where I was hoping there is a way to add the strong element.
void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
Label test = (Label)e.Item.FindControl("Label1");
}
}
I know there are easier ways to do this but I need to do it this way specifically unfortunately.
This seems pretty hacky and doesn't actually give you a strong control to work with, but I suppose something like this might work:
void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
Label test = (Label)e.Item.FindControl("Label1");
Literal literal1 = new Literal();
literal1.Text = "<strong>";
e.Item.Controls.AddAt(e.Item.Controls.IndexOf(test), literal1);
Literal literal2 = new Literal();
literal2.Text = "</strong>";
e.Item.Controls.AddAt(e.Item.Controls.IndexOf(test) + 1, literal2);
}
}
Not easily. So far as I know, there is no <asp:Strong> tag. The easiest thing to do here would be to just put the tag in your code.
However, if you need to optionally implement the strong tag, the same thing can be accomplished by setting the css on your label to font-weight: bold (which is the same as wrapping content in the strong tag), or declaratively by setting the CssClass attribute of the label, ie
Label1.CssClass = "myStrongCssClass";
In the code behind you will need to find the label within the template then
Label1.Font.Bold = true;

read textbox inside a repeater

I have 2 repeaters that print menu headers and menu items - on inside the other.
They look like this:
<asp:Repeater ID="ParentRepeater" runat="server" OnItemDataBound="ParentRepeater_ItemDataBound">
<ItemTemplate>
<h2>
<%#DataBinder.Eval(Container.DataItem, "typenavn") %></h2>
<asp:HiddenField ID="HiddenField1" Value='<%# Eval("id") %>' runat="server" />
<asp:Repeater ID="ChildRepeater" runat="server">
<ItemTemplate>
<table>
<tr>
<td style="width: 200px">
<%#DataBinder.Eval(Container.DataItem, "productName") %>
</td>
<td style="width: 200px">
<%#DataBinder.Eval(Container.DataItem, "pris") %>
</td>
<td>
<asp:HiddenField ID="HiddenField2" runat="server" />
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox><br />
</td>
</tr>
</table>
</ItemTemplate>
</asp:Repeater>
</ItemTemplate>
</asp:Repeater>
It's all good and fun and works.
But now I need to find the different textboxes - in the textboxes you can write how many of the different menu items you want.
I have tried many different things:
Control myControl1 = FindControl("MainContent_ParentRepeater_ChildRepeater_0_HB1_0");
And this:
foreach (RepeaterItem item in ParentRepeater.Items)
{
if (item.ItemType == ListItemType.Item)
{
TextBox txt = (TextBox)item.FindControl(("MainContent_ParentRepeater_ChildRepeater_0_HB1_0")) as TextBox;
// do something with "myTextBox.Text"
break;
}
}
And this:
foreach (RepeaterItem item1 in ParentRepeater.Items)
{
if (item1.ItemType == ListItemType.Item || item1.ItemType == ListItemType.AlternatingItem)
{
ChildRepeater = (Repeater)item1.FindControl("ChildRepeater");
foreach (RepeaterItem item2 in ChildRepeater.Items)
{
if (item2.ItemType == ListItemType.Item || item2.ItemType == ListItemType.AlternatingItem)
{
TextBox txt = (TextBox)item2.FindControl(("ct100$MainContent$ParentRepeater$ct100$ChildRepeater$ct100$HB1")) as TextBox; // MainContent_ParentRepeater_ChildRepeater_0_HB
}
}
}
break;
}
And none of it work. Can anybody out there help me?? How do I get hold of my textbox inside the repeater??
The FindControl function should take the ID of the server control, not the rendered client control. You should be able to do this:
var txt = item.FindControl("TextBox1") as TextBox;
if (txt != null)
{
// found it!
}
To adjust your code:
foreach (RepeaterItem item1 in ParentRepeater.Items)
{
if (item1.ItemType == ListItemType.Item || item1.ItemType == ListItemType.AlternatingItem)
{
ChildRepeater = (Repeater)item1.FindControl("ChildRepeater");
foreach (RepeaterItem item2 in ChildRepeater.Items)
{
if (item2.ItemType == ListItemType.Item || item2.ItemType == ListItemType.AlternatingItem)
{
TextBox txt = (TextBox)item2.FindControl(("TextBox1")) as TextBox;
}
}
}
}
First, you should use FindControl on the repeater you wish to locate a control within - for instance, ParentRepeater.FindControl("controlName") - as opposed to this.FindControl().
Secondly, you should use the ID of the control, not the Client ID - which is a different beast.

Accessing a control within a Repeater

Lets say I have the following:
<asp:Repeater ID="repSubItems" runat="server" DataSource="<%# SubItems %>" >
<ItemTemplate>
<sc:FieldRenderer ID="FieldRenderer1"
FieldName="BlurbSpot_Content_SubHeading"
runat="server"
Item="<%# Container.DataItem as Sitecore.Data.Items.Item %>" />
</ItemTemplate>
</asp:Repeater>
I want to in code behind be able to do:
FieldRenderer1.Style["Width"] = MyCoolWidth;
But within the Repeater I cannot access the FieldRenderer1 control.
You will need to handle the ItemDataBound event of the repSubItems repeater. Example:
protected void repSubItems_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
var fieldRenderer1 = e.Item.FindControl("FieldRenderer1") as Sitecore.Web.UI.WebControls.FieldRenderer;
if (fieldRenderer1 != null)
{
fieldRenderer1.Style["Width"] = MyCoolWidth;
}
}
}
You need to find the row your are looking for specifically in the Repeater and then find the control. Here is an example that can do it for all items in your Repeater:
// repeater item
foreach (Control cr in repSubItems.Controls)
{
// assuming this is your templated control name and not the final output name
FieldRenderer founcControl = cr.FindControl("FieldRenderer1") as FieldRenderer;
founcControl .Style["Width"] = MyCoolWidth;
}
The better way to do this would be to implement the OnDataBinding for your control specifically because then you have no searching to do:
<sc:FieldRenderer ID="FieldRenderer1" FieldName="BlurbSpot_Content_SubHeading"
runat="server" Item="<%# Container.DataItem as Sitecore.Data.Items.Item %>"
OnDataBinding="FieldRenderer1_DataBinding" />
protected void FieldRenderer1_DataBinding(object sender, System.EventArgs e)
{
FieldRenderer rend = (FieldRenderer)(sender);
// you can do whatever you want to rend at this point and it is scoped to ONLY
// the control so you never have to search for it.
rend.Style["Width"] = MyCoolWidth;
}

control image visibility in repeater based on session variable

I'm having trouble figuring out how to control the visibility of an image in a gridview based on a session variable.
<asp:Image runat="server" ID="imgImportedData" Width="20px" Height="20px" ImageUrl="~/images/warning.png" CausesValidation="false" />
I tried using Visible='<%# mySessionVariable %>' but I got a message saying mySessionVariable was unavailable. I think this is because it's in a grid because I am using this variable in the code behind for another part of the page outside of the gridview without any problems.
EDIT: I just realized this in a Repeater control and not a GridView.
I tried both of these and still get The name 'MySession' does not exist in the current context
Visible='<%# (bool)MySession.IsImportedData == "true" ? true : false %>'
Visible='<%# MySession.IsImportedData == "true" ? true : false %>'
<%# is a DataBinding ASP server tag. What happens when you change <%# to <%=?
If that doesn't work, I would suggest setting the column's visibility in a RowDataBound event, like so:
MyGridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
Image imgImportedData = (Image) e.Row.FindControl("imgImportedData");
// Assuming that mySessionVariable isn't already a bool, which it really should be.
imgImportedData.Visible = bool.Parse(mySessionVariable);
}
}
Try this:
<asp:Image runat="server" ID="imgImportedData"
Visible='<%# Session["mySessionVariable"] == "foo" ? true : false %>' />
I got this to work. Thank you for everyone's help. I found an example on this page that helped.
http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.repeater.itemdatabound.aspx
protected void rptAlternateNames_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
if (e.Item.DataItem != null)
{
Image imageImportedData = ((Image)e.Item.FindControl("imgImportedData"));
if (MySession.IsImportedData)
{
imageImportedData.Visible = true;
}
}
}
}

Categories

Resources