I have a repeater on my page:
<asp:Repeater id="attachmentsRepeater" runat="server">
<HeaderTemplate>
<%
if (attachmentsRepeater.Items.Count > 0) {
if (attachmentsRepeater.Items.Count == 1) {
Response.Write("<h3>Attachment</h3>");
Response.Write("<p>");
} else {
Response.Write("<h3>Attachments</h3>");
Response.Write("<ul>");
}
}
%>
</HeaderTemplate>
<ItemTemplate>
<%# OutputAttachment(Container)%>
</ItemTemplate>
<FooterTemplate>
<%
if (attachmentsRepeater.Items.Count > 0) {
if (attachmentsRepeater.Items.Count == 1) {
Response.Write("</p>");
} else {
Response.Write("</ul>");
}
}
%>
</FooterTemplate>
</asp:Repeater>
The original ItemTemplate code looked like this:
<ItemTemplate>
<%
if (attachmentsRepeater.Items.Count > 0) {
if (attachmentsRepeater.Items.Count > 1) {
Response.Write("<li>");
}
%>
<a href="<%# DataBinder.Eval(Container.DataItem, "location") %>">
<%# DataBinder.Eval(Container.DataItem, "name") %>
</a>
<%
if (attachmentsRepeater.Items.Count > 1) {
Response.Write("<li>");
}
}
%>
</ItemTemplate>
In the codebehind, I would like to access the number of Items in the Repeater (line 4):
public string OutputAttachment(RepeaterItem Container) {
string returnValue = "";
Repeater ContainerParent = (Repeater)Container.Parent;
if (attachmentsRepeater.Items.Count > 0) {
if (attachmentsRepeater.Items.Count > 1) {
returnValue += "<li>";
}
returnValue += "<a href=\"" + DataBinder.Eval(Container.DataItem, "location");
if (DataBinder.Eval(Container.DataItem, "location").ToString().EndsWith("/")) {
returnValue += DataBinder.Eval(Container.DataItem, "name");
}
returnValue += ">" + DataBinder.Eval(Container.DataItem, "name") + "</a>";
if (attachmentsRepeater.Items.Count > 1) {
returnValue += "</li>";
}
}
return returnValue;
}
The code that is output is
<h3>Attachment</h3>
<p> </p>
From this output I know that Item.Count == 1 since there is output, the H3 is singular and there is a P tag. If Item.Count > 1, H3 would be plural and there would be a UL tag.
Is this codebehind method being run before the data is bound? Any workarounds for this? Thanks for your help.
This was working for me before, but I had to change it to fulfill a new requirement, which is when it stopped working.
The best place to do your data binding is in the code behind in the page_load event or some other event that is fired when the page is first created.
That way you can control when the data is bound - and you can call the OuputAttachment method after you have bound your data - and you can be sure that the data actually exists.
Related
This is how I will find out about my like a true or false, and I will do my Repeater.
If my like is false then the display content. but if it is true then the display content on the page.
Right now makes this error:
Databinding methods such as Eval(), XPath(), and Bind() can only be
used in the context of a databound control.
<asp:Repeater ID="RepeaterReport" runat="server">
<ItemTemplate>
<%--I have much more different content here.--%>
<% if (Convert.ToBoolean(Eval("like")) != true)
{ %>
<a href="../mentor/report.aspx?like=<%# Eval("IdBesked") %>" class="btn btn-success mr-xs mb-sm">
<i class="fa fa-thumbs-up"></i>Synes godt om
</a>
<% } %>
<%--I have much more different content here.--%>
</ItemTemplate>
</asp:Repeater>
Error are here:
<% if (Convert.ToBoolean(Eval("like")) == false) {%>
Select data:
var MentorBeskedReport = from mb in db.MentorBeskeds
where mb.Id == beskedId && mb.Til_BrugerId == Helper.ReturnBrugerId() && mb.godkendt == true && mb.opretdato < months
select new
{
IdBesked = mb.Id,
Navn = mb.brugere.fornavn + " " + mb.brugere.efternavn,
dag = mb.opretdato,
tekst = mb.tekst,
like = mb.like // Bit in database TRUE/FALSE
};
if (MentorBeskedReport != null)
{
//Report
RepeaterReport.DataSource = MentorBeskedReport.ToList().OrderByDescending(i => i.IdBesked);
RepeaterReport.DataBind();
}
The problem is that you're using the Eval method inside an if statement.
You should change your a tag to runat=server and give it an ID. Then, instead of doing the validation inside your .aspx file, you should add an ItemDataBound event and check it on .aspx.cs:
<asp:Repeater ID="RepeaterReport" ItemDataBound="RepeaterReport_ItemDataBound" runat="server">
<ItemTemplate>
<a id="myAnchor" runat="server" href="../mentor/report.aspx?like=<%# Eval("IdBesked") %>" class="btn btn-success mr-xs mb-sm">
<i class="fa fa-thumbs-up"></i>Synes godt om
</a>
</ItemTemplate>
</asp:Repeater>
public void RepeaterReport_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
if (Convert.ToBoolean(DataBinder.Eval(e.Item.DataItem, "like")) != true)
{
((HtmlControl)e.Item.FindControl("myAnchor")).Visible = false;
}
}
}
Here is my ascx control page code
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="Menu.ascx.cs" Inherits="CrossQueue.Web.Menu" %>
<asp:Label ID="lblMenu" runat="server"></asp:Label>
Here is my c# code
private void CreateMenu()
{
StringBuilder menuHtml = new StringBuilder();
int profileId = 0;
MenuBL menuManager = new MenuBL();
DataTable dtMenu = null;
if (Session["USR_ID"] != null)
{
profileId = Convert.ToInt32(Session["USR_PROFILE"]);
dtMenu = menuManager.GetAllMenuItemsForProfile(profileId);
if (dtMenu != null && dtMenu.Rows.Count > 0)
{
menuHtml.Append("<table id='tblMenu' cellpadding='0' cellspacing='0' width='939' border='0' align='center'>");
menuHtml.Append("<tr>");
menuHtml.Append("<td align='left'>");
menuHtml.Append(Convert.ToString(Session["USR_USERNAME"]));
menuHtml.Append("</td>");
menuHtml.Append("<td width='739' valign='middle' align='right' style='height: 30px;'>");
foreach (DataRow dr in dtMenu.Rows)
{
if (dr["MenuName"].ToString() == "Profile")
{
menuHtml.Append("<img src='/images/home_icon.jpg' width='25' height='25' align='middle' /><a href='AllProfile.aspx>Profile</a> ");
}
else if (dr["MenuName"].ToString() == "User")
{
menuHtml.Append("<img src='/images/home_icon.jpg' width='25' height='25' align='middle' /><a href='AllUsers.aspx>User</a> ");
}
}
menuHtml.Append("</td>");
menuHtml.Append("</tr>");
menuHtml.Append("</table>");
}
lblMenu.Text = menuHtml.ToString();
}
}
When i load the page i only see a html code printed as text and not rendering.Can any one point out what may be wrong
You could use a literal instead of a label.
See this
http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.literal.aspx
You can make a div server accessible by assigning ID and setting runat="server" instead of label and set its InnerHTML = menuHtml.ToString();
<div id="div1" runat="server" ></div>
div1.InnerHTML = menuHtml.ToString();
change the Label
<asp:Label ID="lblMenu" runat="server"></asp:Label>
to Literal as
<asp:Literal ID="lblMenu" runat="server" EnableViewState="false"></asp:Literal>
Here is the deal,
I got a list of documents which is generated by the repeater and his databinding. In my markup i got a class for "li" tag when active or not.
What i just need is to set class="active" on the Li parent tag of my linkbutton when the document is selected.
<asp:Repeater ID="Repeater1" runat="server">
<HeaderTemplate>
<ul>
</HeaderTemplate>
<ItemTemplate>
<li>
<asp:LinkButton ID="lnk" runat="server" CommandArgument='<%# DataBinder.Eval(Container.DataItem, "Id") %>' OnCommand="Get_carte"><%# Container.FindControl("lnk").ClientID %> <%# DataBinder.Eval(Container.DataItem, "Name") %> - <%# DataBinder.Eval(Container.DataItem, "id") %> - <%# DataBinder.Eval(Container.DataItem, "compteur") %></asp:LinkButton></li>
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
</asp:Repeater>
I've finally found a solution for my issue.
#Kapil : Your code works but got issue with the reload of the aspx page, then i can't use this method.
#Aghilas : I based my solution on your code.
In fact i can't use ItemDataBound event because i bind only 1 time my repeater, then i use my OnCommand event on the linkbutton. Here is my aspx code:
<asp:Repeater ID="Repeater1" runat="server" OnItemDataBound="Rpt_DataBound">
<HeaderTemplate>
<ul>
</HeaderTemplate>
<ItemTemplate>
<li runat="server" ID="li">
<asp:LinkButton ID="lnk" class="linkButton" runat="server" CommandArgument='<%# DataBinder.Eval(Container.DataItem, "Id") %>' OnCommand="Get_carte"><%# Container.FindControl("lnk").ClientID %> <%# DataBinder.Eval(Container.DataItem, "Name") %> - <%# DataBinder.Eval(Container.DataItem, "id") %> - <%# DataBinder.Eval(Container.DataItem, "compteur") %></asp:LinkButton></li>
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
</asp:Repeater>
And my GetCarte Method:
protected void Get_carte(object sender, CommandEventArgs e)
{
LinkButton lnk = (LinkButton)sender;
ViewState["liactive"] = lnk.UniqueID.ToString().Substring(0, lnk.UniqueID.ToString().Length - 4);
lbl_carte.Text = lnk.UniqueID + " " + e.CommandArgument.ToString();
foreach (RepeaterItem rI in Repeater1.Items)
{
if (rI.ItemType == ListItemType.Item || rI.ItemType == ListItemType.AlternatingItem)
{
string liactiv = "";
if (ViewState["liactive"] != null)
liactiv = ViewState["liactive"].ToString();
var li = (HtmlControl)rI.FindControl("li");
if (li.UniqueID.ToString().Substring(0, li.UniqueID.ToString().Length - 3) == liactiv) //Adjust your condition
li.Attributes.Add("class", "active");
else
li.Attributes.Remove("class");
}
}
}
Thanks for your help.
PS: I put ID in ViewState in case of needing the value in another part of my code. I also can replace my substring by lastindexof method.
Code Behind - C# :
You can add runat="server" and id="" to your li, in order to modify in your code behind
void Repeater_ItemDataBound(Object Sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
var li = (HtmlControl)e.Item.FindControl("IdOfYourLI");
if(condition) //Adjust your condition
{
li.Attributes.Add("class", "active");
}
}
}
You can also modify with JavaScript :
You add to element id and use GetElementById method
youIdOfControlLI.className = 'active';
Using jQuery:
jsFiddle working link
Set class="linkButton" to you LinkButtons.
<asp:LinkButton ID="lnk" class="linkButton" />
Use the following jQuery Code to to set the Class on the li:
$(function () {
$(".linkButton").each(function (index) {
$(this).on("click", function () {
$(".linkButton").each(function (index) {
$(this).closest("li").removeClass("active");
});
$(this).closest("li").addClass("active");
});
});
});
I'm using repeater to create dynamic ul li list
Is it possible to control class whether item is first or last?
Something like:
class="<%# if(Container.ItemIndex == 0)
{
class = ...
}
) %>"
by the way what does it really mean: <%# in ASP.NET
What is the difference between <%# and <%=?
It is quite easy to determine whether the item is first or not (Container.ItemIndex == 0), but to determine whether the element is last or not you have to use a custom property which will be initialized right with data binding:
protected int ItemCount { get; set; }
Here is a repeater example:
<asp:Repeater runat="server" ID="repeater">
<HeaderTemplate>
<ul>
</HeaderTemplate>
<ItemTemplate>
<li class="<%# GetItemClass(Container.ItemIndex) %>">
<%# Container.DataItem %>
</li>
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
</asp:Repeater>
here is an example of data binding:
public override void DataBind()
{
var data = new string[] { "first", "second", "third" };
this.ItemCount = data.Length;
repeater.DataSource = data;
repeater.DataBind();
}
and finally a helper method:
protected string GetItemClass(int itemIndex)
{
if (itemIndex == 0)
return "first";
else if (itemIndex == this.ItemCount - 1)
return "last";
else
return "other";
}
This will produce:
<ul>
<li class="first">
first
</li>
<li class="other">
second
</li>
<li class="last">
third
</li>
</ul>
I typically use something like the following:
<asp:Repeater ID="rptItems" runat="server" ViewStateMode="Disabled">
<ItemTemplate>
<li<%# Container.ItemIndex == ((IList)((Repeater)Container.Parent).DataSource).Count-1 ? " class='last'" : ""%>>
...
</li>
</ItemTemplate>
</asp:Repeater>
If possible, I'd recommend using something like jQuery for this as it makes implementing this type of functionality very easy. For example, you could have something like this:
<asp:Repeater id="MyRepeater" runat="server">
<HeaderTemplate><table class="MyRepeater"></HeaderTemplate>
<FooterTemplate></table></FooterTemplate>
<ItemTemplate><tr><td>My Data</td></tr></ItemTemplate>
</asp:Repeater>
$("table.MyRepeater tr:last").attr("class", "last");
Try somwthing like this, if you are not using jQuery
<asp:Repeater ID="Repeater1" runat="server">
<ItemTemplate>
<asp:Label ID="Label1" CssClass='<%# Container.ItemIndex == 0 ? "first" : "notFirst" %>' runat="server" Text="Label"></asp:Label>
</ItemTemplate>
</asp:Repeater>
I modified nelsestu's solution and came up with:
<%# Container.ItemIndex == ((System.Data.DataTable)((Repeater)Container.Parent).DataSource).Rows.Count-1 ? "</div>" : string.Empty %>
As for your question on the difference between <%= and <%#, please see the following links:
Code Render Blocks:
http://msdn.microsoft.com/en-us/library/k6xeyd4z(v=vs.71).aspx
Data Binding Expression Syntax:
http://msdn.microsoft.com/en-us/library/bda9bbfx(v=vs.71).aspx
I wasn't able to use Alex's answer directly. Here are the modifications I made that worked for me. Using Alex's "repeater example" for the asp:Repeater tag, use this in the code behind:
private string[] data = new string[] { "first", "second", "third" };
protected int ItemCount { get; set; }
private void Page_Load(object sender, EventArgs e)
{
// normally one would fetch the data here right before binding like this:
// data = SomeService.SomeMethodToGetData();
repeater.DataSource = data;
repeater.DataBind();
}
public override void DataBind()
{
ItemCount = data.Count();
}
protected string GetItemClass(int itemIndex)
{
if (itemIndex == 0)
return "first";
else if (itemIndex == this.ItemCount - 1)
return "last";
else
return "other";
}
I usually do it like this for the last item
Public m_recordCount As Integer
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
ltrlTitle.Text = m_title
Using Context As New MyEntities
Dim m_lst = Context.getHotRecords(m_location).ToList
m_recordCount = m_lst.count()
rptListings.DataSource = m_lst
rptListings.DataBind()
End Using
End Sub
and here is how I use it in HTML markup
<div <%# IIf(m_recordCount - 1 = Container.ItemIndex, "class='clearBorder'", "")%>>
For those needing this in VB, here's what works for me.
<span runat="server" class='divider'
Visible="<%# Container.ItemIndex < DirectCast(DirectCast(Container.Parent,Repeater).DataSource,List(Of IList)).Count()-1 %>">|</span>
I needed a divider to show for all items except for the last one.
If your are using controls within your ItemTemplate you can do something like the following, add OnItemDataBound event.
<asp:Repeater ID="RptId" runat="server" OnItemDataBound="OnItemDataBound">
<ItemTemplate>
<asp:Panel runat="server" ID="PnlCtrlItem">
<%#Eval("Content") %>
</asp:Panel>
</ItemTemplate>
</asp:Repeater>
protected void OnItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemIndex == 0)
((Panel) e.Item.FindControl("PnlCtrlItem")).CssClass = "first";
//or the following to have your control indexed
((Panel) e.Item.FindControl("PnlCtrlItem")).CssClass = string.Format("item-{0}",e.Item.ItemIndex);
}
I am looking for paging(Top,Bottom) functionality for gridview(or any databind controls)
i am using .net framework 2.0.
i would like to have pointers
thank you
solution:
i used jQuery plugin jquery.tablePagination.0.1.js for my solution
You can asp:repeater for this this can easily handle by Repeater control.
This aspx page code
<asp:Repeater ID="rptImages" runat="server" onitemcommand="rptImages_ItemCommand">
<ItemTemplate >
<div class="image"> <a ><asp:Image ID="Image1" runat="server" imageUrl=' <%# Eval("ImageUrl") %>' /></a> </div>
</ItemTemplate>
</asp:Repeater>
<asp:Repeater ID="rptPages" Runat="server"
onitemcommand="rptPages_ItemCommand">
<HeaderTemplate>
<table cellpadding="0" cellspacing="0" border="0">
<tr class="text">
<td><b style="color:White;">Page:</b> </td>
<td>
</HeaderTemplate>
<ItemTemplate>
<asp:LinkButton ID="btnPage" ForeColor="White"
CommandName="Page"
CommandArgument="<%#
Container.DataItem %>"
CssClass="text"
Runat="server"><%# Container.DataItem %>
</asp:LinkButton>
</ItemTemplate>
<FooterTemplate>
</td>
</tr>
</table>
</FooterTemplate>
</asp:Repeater>
this code behind page code
public void LoadData()
{
try
{
PagedDataSource pgitems = new PagedDataSource();
DataView dv = new DataView(dtImage);
pgitems.DataSource = dv;
pgitems.AllowPaging = true;
pgitems.PageSize = 8;
pgitems.CurrentPageIndex = PageNumber;
if (pgitems.PageCount > 1)
{
rptPages.Visible = true;
ArrayList pages = new ArrayList();
for (int i = 0; i < pgitems.PageCount; i++)
pages.Add((i + 1).ToString());
rptPages.DataSource = pages;
rptPages.DataBind();
}
else
rptPages.Visible = false;
rptImages.DataSource = pgitems;
rptImages.DataBind();
}
catch { }
}
public int PageNumber()
{
get
{
if (ViewState["PageNumber"] != null)
return Convert.ToInt32(ViewState["PageNumber"]);
else
return 0;
}
set
{
ViewState["PageNumber"] = value;
}
}
public void itemGet()
{
try
{
var Images = dataContext.sp_getCards(categoryId);
PagedDataSource pds = new PagedDataSource();
pds.DataSource = Images;
pds.AllowCustomPaging = true;
pds.AllowPaging = true;
pds.PageSize = 8;
pds.CurrentPageIndex = CurrentPage;
lblCurrentPage.Text = "Page: " + (CurrentPage + 1).ToString() + " of "
+ pds.PageCount.ToString();
// Disable Prev or Next buttons if necessary
//cmdPrev.Enabled = !pds.IsFirstPage;
//cmdNext.Enabled = !pds.IsLastPage;
rptImages.DataSource = pds;
rptImages.DataBind();
}
catch { }
}
protected void rptPages_ItemCommand(object source, RepeaterCommandEventArgs e)
{
try
{
PageNumber = Convert.ToInt32(e.CommandArgument) - 1;
LoadData();
}
catch { }
}
This will be hardly achievable in GridView because it uses rigid table structure with only single pager template. You need two - one on the top and one on the bottom. For such control you need Repeater (.NET 2.0) or ListView (.NET 3.5). When you have buttons placed you can handle their click or command events and rebind your grid to newly selected set of data. In repeater you will probably have to store current page and number of items per page somewhere (ViewState). If you want jQuery based paging (client side) with partial rendering you need to handle client side onclick and add AJAX call to get new page based on pushed button.
i used jQuery plugin jquery.tablePagination.0.1.js for my solution
refer this link
As others have said, I don't think this is a good job for GridView. I'd take a look at ListView or Repeater as they are better suited for something like this and quite easy to add custom pagination to.