Loading repeater when binding gridview in asp.net - asp.net

I have a gridview like this:
<asp:GridView ID="gv1" AutoGenerateColumns="false" BorderWidth="0" runat="server" >
<Columns>
<asp:TemplateField>
<ItemTemplate>
<span style="font-family:Tahoma; font-size:14px;">
<u> <a href="<%#DataBinder.Eval(Container.DataItem,"ShUrl")%>">
<%#DataBinder.Eval(Container.DataItem,"PostTitle")%>
</a>
</u>
<br />
</span>
<asp:Repeater ID="rp1" runat="server">
<HeaderTemplate>
<ul>
</HeaderTemplate>
<ItemTemplate>
<li >
<%# Eval("TagName")%>
</li>
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
</asp:Repeater>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Now I am able to load successfull ShUrl and PostTitle. I am bringing titleId from the database also.
Now as usual, a post might have several tag. So I want to load the repeater for the particular titleId.
On server side, I am simply binding the gv1 from the datable.
Now how to load tags for the titleid:
I have already written the function on the server side, might help you all to guide me:
private void LoadtagList(int titleId)
{
// calling DAL
rp1.DataSource = db.GetAllTagsForPost(titleId);
rp1.DataBind();
}

you have to use GridView RowDataBound Event for that
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if(e.Row.RowType == DataControlRowType.DataRow)
{
System.Data.DataRowView dr = (System.Data.DataRowView)e.Row.DataItem;
if (Convert.ToString(dr["titleId"]) != "")
{
Repeater rp1 = (Repeater)e.Row.Findcontrol("rp1");
rp1.DataSource = db.GetAllTagsForPost(titleId);
rp1.DataBind();
}
}
}

Related

how to understand which rows selected in repeater?

I have a slideshow that images load from sql server.
here is my html code:
<!-- Elastislide Carousel -->
<ul id="Ul1" class="elastislide-list">
<asp:Repeater ID="Repeater2" runat="server">
<ItemTemplate>
<li>
<asp:Label ID="lbl" runat="server" Text='<%#Eval("IDMusic") %>' Visible="True"></asp:Label>
<asp:ImageButton ID="ImageButton1" runat="server" ImageUrl='<%#Eval("ImageUrl") %>' Width="250px" Height="250px" OnClick="ImageButton1_Click" />
</li>
</ItemTemplate>
</asp:Repeater>
</ul>
<!-- End Elastislide Carousel -->
<br /><br />
</div>
</div>
Now when, I run Project and user click on one of the imageButtons, I want to understand what is he/she clicked? for example he/she click on second ImageButton, Then I want to save IDMusic into a session and use this session in another page but I don't know how can i get IDmusic user clicked on?
here is my code behind :
protected void ImageButton1_Click(object sender, ImageClickEventArgs e)
{
foreach (RepeaterItem item in Repeater2.Items)
{
Label lbl = (Label)item.FindControl("lbl");
if (lbl != null)
{
Session["selectedmusicID"] = lbl.Text;
}
}
Response.Redirect("music.aspx");
}
There is no easy way to do so while handling click on the image itself. However you can leverage ItemCommand event here, which is a repeater event. Basically when some control is clicked inside the repeater, it generates a command in repeater which you can handle, and you can have item-specific arguments for it.
To define a command and args:
<asp:ImageButton ID="ImageButton1" ... CommandName="Select" CommandArgument='<%#Eval("IDMusic") %>' />
Command name here is custom, choose whatever you like. Now subscribe to the event of the repeater:
<asp:Repeater ID="Repeater2" runat="server"
OnItemCommand="Repeater2_ItemCommand">
And to handle:
protected void Repeater2_ItemCommand(object source, RepeaterCommandEventArgs e)
{
if (e.CommandName == "Select") //just in case you have more than one
{
e.CommandArgument //here is your ID
}
}

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 :)

How to get Reference to the label in repeater item in code behind

<asp:repeater id="rpt" run="server">
<ItemTemplate>
<asp:LinkButton id="Delete" runat="server" OnCommand="Delete_Command"></asp:linkButton>
<asp:label id="lblMessage" run="server">
</ItemTemplate>
</asp:repeater>
Code Behind:
protected void Delete_Command(object sender, CommandEventArgument e)
{
}
how i get the reference to the "lblMessage" in Delete_Command.
Try this:
protected void Delete_Command(object sender, CommandEventArgs e)
{
LinkButton button = (LinkButton)sender;
Label label = (Label)button.NamingContainer.FindControl("lblMessage");
// do something with the label
}
If you:
Have bound the repeater
Have ViewState enabled
Do not re-bind the repeater earlier in the post back
this should work. If not, please verify that the id of the label is indeed exactly the same as in the ...FindControl("lblMessage");. Also make sure that runat="server" is set on all the controls involved.
Edit: One more thing to check: Search the markup file (the .aspx file) and check if there are any other controls that also use the same event in the code behind. If another control is using the same event handler and that control is not in the repeater, the label will not be found.
means are you want find a lable in Delete_Command event?
in aspx
<asp:Repeater ID="rpt" runat="server">
<ItemTemplate>
<asp:LinkButton ID="Delete" runat="server" OnCommand="Delete_Command"></asp:LinkButton>
<asp:Label ID="lblMessage" run="server">
</ItemTemplate>
</asp:Repeater>
in aspx.cs
protected void Delete_Command(object sender, CommandEventArgs e)
{
foreach (RepeaterItem item in rpt.Items)
{
Label lblMessage = item.FindControl("lblMessage") as Label;
if (lblMessage != null)
{
lblMessage.Text = "";
}
}
}
If You want to make it in your way use following code in
protected void Repeater1_ItemCommand(object source, CommandEventArgs e)
{
(((LinkButton)source).NamingContainer).FindControl("lblName")
}
Another approach.. But something that you can buy
aspx
<asp:Repeater ID="Repeater1" runat="server"
onitemcommand="Repeater1_ItemCommand">
<ItemTemplate>
<asp:Label ID="lblName" runat="server" Text='<%=Eval("Name") %>' ></asp:Label>
<asp:LinkButton runat="server" CommandName="Delete_Command" Text="sd"></asp:LinkButton>
</ItemTemplate>
</asp:Repeater>
.cs
protected void Delete_Command(object sender, CommandEventArgument e)
{
if(e.CommandName != null)// Conditional Check
{
Label label = e.Item.FindControl("lblMessage");
// do something with the label
}
}

how do i get access to the label inside gridview/repeater

as you can see in my code... i have a label inside ItemTemplate and what i want is when i click on that particular control i would like to access to the label so that i can update the status...
<asp:Repeater ID="Repeater1" runat="server" DataSourceID="ObjectDataSource1" OnItemCreated="Repeater1_ItemCreated" OnItemDataBound="Repeater1_ItemDataBound">
<ItemTemplate>
Book:
<asp:Label ID="lblStatus" runat="server"></asp:Label>
<Mycontrol:Content1 ID="EmpControl" runat="server" OnMyControlClick="EmpControl_clicking" />
<br />
</ItemTemplate>
</asp:Repeater>
protected void EmpControl_clicking(object sender, EmployeeEventArgs e)
{
// how do i get access to the lblStatus???
}
You will need to use the FindControl method to access controls within templates:
protected void EmpControl_clicking(object sender, EmployeeEventArgs e)
{
MyControl myControl = (MyControl)sender;
Label c = (Label)myControl.Parent.FindControl("lblStatus");
}

display many rows from DB by normal line?

When I have a table in database with many rows
and I want to display them by normal line (Not with Gridview). Like:
You teach these classes:
class 1/1, class 2/1, class 3/1
we take (1/1 and 2/1 and 3/1) from database.
how can I do it ?
note: I use LINQ to deal with database.
Using a repeater seems to be the easiest way to me. It would look something like this.
<div>
You teach these classes:
<asp:Repeater
ID="rptListOfClasses"
runat="server"
DataSourceID="linqDataSource" >
<ItemTemplate>
<span> class <%# Eval("ClassDate") %>, </span>
</ItemTemplate>
</asp:Repeater>
</div>
<asp:ListView ID="lvClass" runat="server" DataSourceID="LinqDataSource1" OnItemDataBound ="lvResult_ItemDataBound" >
<LayoutTemplate>
You teach these classes:
<asp:PlaceHolder runat="server" ID="itemPlaceHolder" ></asp:PlaceHolder>
</LayoutTemplate>
<ItemTemplate>
<asp:Label ID="lblClass" runat="server" Text='<%# DataBinder.Eval(Container.DataItem, "Class") + ", " %>' ></asp:Label>
</ItemTemplate>
</asp:ListView>
<asp:LinqDataSource ID="LinqDataSource1" runat="server"
ContextTypeName="MyDataContext" TableName="ClassList"
onselected="LinqDataSource1_Selected">
</asp:LinqDataSource>
Code Behind:
//remove the last comma(,)
public class Test : System.Web.UI.Page
{
int iCount = 0;
protected void lvResult_ItemDataBound(object sender, ListViewItemEventArgs e)
{
if (e.Item.ItemType == ListViewItemType.DataItem)
{
Label lblClass = e.Item.FindControl("lblClass") as Label;
ListViewDataItem lvItem = e.Item as ListViewDataItem ;
if (lblClass != null)
if (lvItem.DataItemIndex == (iCount - 1))
lblClass.Text = lblClass.Text.Substring(0, lblClass.Text.ToString().Length - 2);
}
}
protected void LinqDataSource1_Selected(object sender, LinqDataSourceStatusEventArgs e)
{
iCount = e.TotalRowCount;
}
}

Resources