Reaching repeater item: The Logic - asp.net

Here is my design page:
<asp:MultiView ID="mvProducts" runat="server" ActiveViewIndex="0">
<asp:View runat="server" ID="mvProducts1">
<asp:Repeater ID="rptDiscount" runat="server">
<ItemTemplate>
<div class="divProduct1">
<div class="divProductHeader">
<asp:Panel ID="pnlDiscount" runat="server" CssClass="divProductHeaderDiscount" Visible="true">
<div class="menuTextTopSpacer"></div>
<asp:Label ID="lblDiscount" runat="server" Text='<%#Eval("discount") %>'></asp:Label>
</asp:Panel>`
I just want to reach pnlDiscount item but I dont know how. I made a search but it just helped to increase my confusion.
Indeed, I want to learn the logic on finding a control in a repeater.

Use ItemDataBound on your reapter then use FindContol() to get to the Panel
protected void rptDiscount_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
Panel myPanel= e.Item.FindControl("pnlDiscount") as Panel;
//Do some work
}

Related

Connecting Session from a repeater's item to another page doesn't work

I want to take the text in the text box from the particular item in the repeater that was clicked, and use it on the page ViewRecipe2.aspx.
Currently, when you click a button on one of the items, it returns back to the repeater's page, but the repeater does not appear, instead of moving to the page ViewRecipe2.aspx.
This is my repeater in aspx:
<asp:Repeater ID="RepeaterR" runat="server">
<ItemTemplate>
<div class="wrapper">
<table>
<div class="box">
<div class="property-card">
<div class="property-image">
<div class="property-image-title">
</div>
</div>
<div class="property-description">
<asp:Button CssClass="h5" runat="server" ID="Button1" OnClick="Button1_Click" Text=<%# Eval("recipeName")%> BackColor="Transparent" BorderColor="Transparent"/>
<p><%#Eval("avgRating") %> stars</p>
<asp:Image class="img" runat="server" src=<%#Eval("recipePic") %> />
<asp:TextBox ID="hiddenTB" runat="server" Text=<%# Eval("recipeName")%> Visible="false"></asp:TextBox>
</div>
</div>
</div>
</table>
</div>
</ItemTemplate>
</asp:Repeater>
This is the code behind on c#:
protected void Button1_Click(object sender, EventArgs e)
{
RepeaterItem item = (sender as Button).NamingContainer as RepeaterItem;
string VR = (item.FindControl("hiddenTB") as TextBox).Text;
if (VR!=null)
{
Session["selectedRecipe"] = VR;
Response.Redirect("ViewRecipe2.aspx");
}
}
This is ViewRecipe2.aspx:
<asp:TextBox ID="TextBoxP" runat="server"></asp:TextBox>
And the code behind:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
string theRecipeName = (Session["selectedRecipe"]).ToString();
TextBoxP.Text = theRecipeName;
}
}
Well, text box or hidden field is "never" null.
but, you need quotes around that "text" setting of the hidden field.
<asp:TextBox ID="hiddenTB" runat="server"
Text='<%# Eval("recipeName")%>' Visible="false">
</asp:TextBox>
Also, keep in mind, that with visible=false, then the markup is NOT sent nor rendered client side. This means that client side js code can't use that text box, but server side code can just fine grab the textbox, and then the value as you have.
However, while you "should" have those single quotes?
it should still have worked.
I would for testing, remove the Visible="false", and then you can actually see + verify that the value is correct.

Binding ListView Field to Value in Code-Behind

I'm displaying fields from a DB call in a ListView. I had to re-code my database query because of an issue with repeating groups. I also didn't want to have to deal with nested ListViews. So now I am trying to set the header to the value of radio button list selection. I was trying to write a custom method to return that value but could not remember the syntax.
How can I set the header in the LayoutTemplate from the code-behind so that it doesn't repeat?
<LayoutTemplate>
<div class="resultsGrid">
<strong><%# GetHeader() %></strong>
<asp:PlaceHolder runat="server" ID="resultsPlaceHolder">
</asp:PlaceHolder>
</div>
</LayoutTemplate>
<ItemTemplate>
// rest of data
</ItemTemplate>
I was able to solve this as follows:
<asp:ListView ID="resultsList" ItemPlaceholderID="resultsPlaceHolder"
OnItemCreated="ResultsList_ItemCreated" runat="server">
<LayoutTemplate>
<div class="resultsGrid">
<strong><asp:Label ID="headerLabel" runat="server"></asp:Label></strong>
<asp:PlaceHolder runat="server" ID="resultsPlaceHolder">
</asp:PlaceHolder>
</div>
</LayoutTemplate>
<ItemTemplate>
// rest of data
</ItemTemplate>
</asp:ListView>
And in the code-behind:
protected void ResultsList_ItemCreated(object sender, ListViewItemEventArgs e)
{
if (e.Item is ListViewItem)
{
Label tempLabel = resultsList.FindControl("headerLabel") as Label;
tempLabel.Text = ViewState["ParkName"].ToString();
}
}

Why does GridView inside a Repeater (or other similar controls) has the event PageIndexChanging as NOT IMPLEMENTED

Simply I want to know WHY!
Is it the DataSource Type of the GridView? or the Repeater inner implementation?
The error text:
The GridView 'grdArticles' fired event PageIndexChanging which wasn't handled.
Here's the Markup code, I think it's familiar enough for everyone.
<asp:Repeater ID="rptCategories" DataSourceID="ldsCategories" runat="server">
<ItemTemplate>
<asp:GridView runat="server" ID="grdArticles" AllowPaging="true" GridLines="None" DataKeyNames="id" AutoGenerateColumns="false" DataSource='<%# Eval("Articles") %>'>
<Columns>
<asp:TemplateField ShowHeader="false" ItemStyle-Width="100%" FooterStyle-Width="100%">
<ItemTemplate>
<div class="article-menu-item">
<h1>
<asp:HyperLink ID="lnkTitle" CssClass="article-menu-title" runat="server" Text ='<%# Eval("title") %>'
NavigateUrl='<%# Vars.ArticleUrl + "?action=view&id=" + Eval("id") %>' ></asp:HyperLink>
</h1>
<!-- Date -->
<div class="article-menu-date">
<asp:Label ID="Label1" runat="server" Text='<%# Eval("date") %>'></asp:Label>
</div>
<!-- Meta Content -->
<div class="article-menu-meta">
<asp:Label ID="lblContent" runat="server" Text='<%# Bind("meta") %>'></asp:Label>
</div>
<div class="article-menu-delete">
<asp:LinkButton ID="btnDelete" Text="Delete" runat="server" OnClick="btnDelete_Click" TargetID='<%# Eval("id") %>' />
</div>
<!-- Line -->
<div style="border-bottom: 1px solid #ccc"></div>
</div>
</ItemTemplate>
</asp:TemplateField>
</Columns>
<EmptyDataTemplate>
<p>No items to view!</p>
</EmptyDataTemplate>
</asp:GridView>
<br />
</ItemTemplate>
</asp:Repeater>
EDIT:
If I implement the OnPageIndexChanging event using the code (And modified the aspx gridview markup to handle the event):
ASPX:
<asp:GridView runat="server" ID="grdArticles" AllowPaging="true" OnPageIndexChanging="grdArticles_PageIndexChanging" GridLines="None" DataKeyNames="id" AutoGenerateColumns="false" DataSource='<%# Eval("Articles") %>'>
cs:
protected void grdArticles_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
GridView grd = sender as GridView;
grd.PageIndex = e.NewPageIndex;
grd.DataBind();
}
Another exception thrown:
Databinding methods such as Eval(), XPath(), and Bind() can only be used in the context of a databound control.
Edit #2:
After following Mr #Garrison solution, and handling the Repeater itemDataBound event using the code:
protected void rptCategories_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
GridView grd = e.Item.FindControl("grdArticles") as GridView;
if (grd != null)
{
DatabaseDataClassesDataContext dc = new DatabaseDataClassesDataContext();
grd.DataSource = dc.Articles.Where(a => a.category_id == (e.Item.DataItem as Category).id);
grd.DataBind();
}
}
Got another problem: No exceptions thrown, but when navigating to another page, the GridView shows NO ROWS!!
I really think that there is an issue in the repeater core implementation!
You have two options:
Remove Paging: Set AllowPaging="false" in your GridView.
Implement Paging: Set OnPageIndexChanging="grdArticles_PageIndexChanging"
Create a method in your code behind that looks like this:
protected void grdArticles_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
grdArticles.PageIndex = e.NewPageIndex;
grdArticles.DataBind();
}
Now that we're past the first issue, let's tackle the second one. You need to handle your Repeater's ItemDataBound event. Inside there, first find your GridView with the following code:
var grdArticles = (GridView)e.Item.FindControl("grdArticles");
Now you have access to the GridView, but you've got to find the set of Articles you want to data bind to the GridView. I don't know how you're retrieving your data, so I leave that portion up to you, but once you find your list of articles to bind, use the following code:
grdArticles.DataSource = relevantArticles; // relevantArticles is a stand-in variable name, because I don't know how you're going to do it
grdArticles.DataBind();
I've figured out -with the help of others answers- that's the problem is with the DataSource type, which is -in my example- the Eval("Items"), I don't know really what's the type of it, but it's not supporting auto paging.
So, one way to step out of it -without rewriting paging logic and writing lots of code and get some mess with Sessions and querying- is to handle the ItemDataBound of the container of the GridView, I mean the Repeater or DataList, or you can handle the OnPreRender of the GridView and create the DataSource that supports the auto paging like LinqDataSource.
You may also need to handle the PageIndexChanging of the GridView like what #Garrison told us:
protected void grdArticles_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
grdArticles.PageIndex = e.NewPageIndex;
grdArticles.DataBind();
}
After that I got everything work :)

ASP.NET MultiView with multiple repeaters

I have a problem and I need your opinion. I have a control with a MultiView and each view will be a different render for the control's output, it will be about 10 different views. Inside each view I will have a repeater that will repeat a few rows, this repeater will be the same for all views and since the MultiView only allows 1 view to be show at any one time, I though to have the repeater with the same ID, so I don't have to make 10 bindings and create 10 OnItemDataBound events with the exact same code in it, but ASP.NET don't let me have the repeater with the same ID (it should be smarter than that for this case). I am using C# and v4 of the framework.
Here's the MultiView code:
<asp:MultiView id="MultiView" runat="server">
<asp:View id="h400" runat="server">
<div class="latest_Wide">
<h3>Wide</h3>
<asp:Repeater id="rptLatest" runat="server" OnItemDataBound="rptLatest_OnItemDataBound">
<ItemTemplate>
<p>• <asp:Literal id="litPostTitle1" runat="server" /></p>
</ItemTemplate>
</asp:Repeater>
</div>
</asp:View>
<asp:View id="h200" runat="server">
<div class="latest_Narrow">
<h3>Narrow</h3>
<asp:Repeater id="rptLatest" runat="server" OnItemDataBound="rptLatest_OnItemDataBound">
<ItemTemplate>
<p>• <asp:Literal id="litPostTitle2" runat="server" /></p>
</ItemTemplate>
</asp:Repeater>
</div>
</asp:View>
...
</asp:MultiView>
How can I solve this problem. Remember I don't want to make 10 repeater bindings and have 10 OnItemDataBound events with the exact same code, for the case you suggest to give the repeaters different IDs.
This isn't pretty... but:
Assume your ASCX:
<asp:MultiView id="mvPostDisplay" runat="server">
<asp:View id="h400" runat="server">
<div class="latest_Wide">
<h3>Wide</h3>
<asp:Repeater runat="server" OnItemDataBound="rptLatest_OnItemDataBound">
<ItemTemplate>
<p>• <asp:Literal id="litPostTitle1" runat="server" /></p>
</ItemTemplate>
</asp:Repeater>
</div>
</asp:View>
<asp:View id="h200" runat="server">
<div class="latest_Narrow">
<h3>Narrow</h3>
<asp:Repeater runat="server" OnItemDataBound="rptLatest_OnItemDataBound">
<ItemTemplate>
<p>• <asp:Literal id="litPostTitle2" runat="server" /></p>
</ItemTemplate>
</asp:Repeater>
</div>
</asp:View>
...
</asp:MultiView>
In your codebehind:
private void DataBindRepeater()
{
View activeView = this.mvPostDisplay.GetActiveView();
Repeater myRepeater = this.FindRepeater(activeView);
if (myRepeater != null)
{
myRepeater.DataSource = this.GetDataSourceFormSomewhere();
myRepeater.DataBind();
}
}
private Repeater FindRepeater(Control container)
{
if (container is Repeater)
{
return container as Repeater;
}
else
{
foreach (Control c in container.Controls)
{
Repeater retVal = this.FindRepeater(c);
if (retVal != null)
{
return retVal;
}
}
return null;
}
}
And simply call DataBindRepeater after you've determined the appropriate view. Please note rptLatest will not be set, therefor you will need to get a reference to your repeater in your handler using either the sender, FindRepeater, or possibly something less hackish.
Have you considered making the repeater a user control? This way you have all the repeater binding code once in your user control. Each view will have it's own instance of the usercontrol.
Is this a direction you are willing to take?

Shading every other row in a VB.net Listview?

I have been Googling this for about a day now, and every post I find is too old and Visual Studio doesn't recognize some pieces of code that people have posted. I have a dynamically populated Listview. I would really like every other line to be shaded for readability purposes, and just can't figure it out.
Everything I try to do messes with the Modal PopupExtender that I have inside of the Listview. It trys to shade the lines inside the PopUpBox too. This is one of the Listviews that I would like shaded.
<!-- Descriptions -->
<asp:TabPanel ID="tab2" runat="server" HeaderText="Descriptions">
<HeaderTemplate>Descriptions</HeaderTemplate>
<ContentTemplate>
<ul class="info">
<asp:ListView ID="lvDescriptions" runat="server" DataSourceID="dsMarketingDescriptions" DataKeyNames="MarketingID">
<ItemTemplate>
<li>
<asp:LinkButton ID="ViewDescriptionButton" runat="server"><%#Eval("MarketingTitle")%></asp:LinkButton>
<asp:Panel ID="ViewDescriptionPanel" runat="server" CssClass="DescModalPopup"> <div class="PopupHeader" id="PopupHeader">View Description
<asp:ImageButton ID="CancelDescriptionButton" runat="server" ImageUrl="../../images/exit.png" AlternateText="" Style="float:right;"/>
</div>
<asp:Label ID="Description" runat="server" style="padding:5px;"><%# Eval("MarketingData") %></asp:Label>
</asp:Panel>
<asp:ModalPopupExtender ID="ViewDescriptionModal" runat="server" BackgroundCssClass="modalBackground" DropShadow="false" DynamicServicePath="" Enabled="true" PopupControlID="ViewDescriptionPanel" TargetControlID="ViewDescriptionButton" CancelControlID="CancelDescriptionButton"></asp:ModalPopupExtender>
</li>
</ItemTemplate>
</asp:ListView>
</ul>
</ContentTemplate>
</asp:TabPanel>
Try using the AlternatingItemTemplate to specify a different background color for alternating items.
Are you trying to do something like this with the ModalPopupExtender?:
protected void ListView1_ItemDataBound(object sender, ListViewItemEventArgs e)
{
Panel pnl = e.Item.FindControl("Panel1") as Panel;
if (pnl != null)
{
pnl.BackColor = ListView1.Items.IndexOf(e.Item) % 2 == 1 ? Color.PeachPuff : Color.White;
}
}

Resources