Bind 5 items in each row of repeater - c#

I have a set of items coming from the database. Their number may vary. I have bound them in a repeater. Now my following example will explain what I want:
I have 11 items coming from database, I want them to be grouped in terms of 5 items per row.
1st row: 5 items.
2nd row: 5 items.
3rd row: 1 item.
Currently, I am just binding them in a repeater. How do I do this?

Yes. It is possible:
<asp:Repeater ID="rptItems" runat="server">
<ItemTemplate>
<asp:Literal runat="server" Text='<%# Eval("Value") %>'></asp:Literal>
<div style="clear: both" runat="server" Visible="<%# (Container.ItemIndex+1) % 5 == 0 %>"></div>
</ItemTemplate>
</asp:Repeater>
It produces following results for the sequence of numbers:
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20

if you can use ListView, then you can use GroupItemCount . some thing like this MSDN Example
<asp:ListView ID="ContactsListView"
DataSourceID="yourDatasource"
GroupItemCount="5"
runat="server">
<LayoutTemplate>
<table id="tblContacts" runat="server" cellspacing="0" cellpadding="2">
<tr runat="server" id="groupPlaceholder" />
</table>
</LayoutTemplate>
<ItemTemplate>
<div> your Items here </div>
</ItemTemplate>
<GroupTemplate>
<tr runat="server" id="ContactsRow" style="background-color: #FFFFFF">
<td runat="server" id="itemPlaceholder" />
</tr>
</GroupTemplate>
<ItemSeparatorTemplate>
<td runat="server" style="border-right: 1px solid #00C0C0"> </td>
</ItemSeparatorTemplate>
</asp:ListView>

If you want to stick with a Repeater, I can think of two approaches.
Firstly, you could stick with a flat list of items and make the repeater insert a "new line" after each 5th item. You should be able to do this in the <ItemTemplate> with a block like
<% if ((Container.DataItemIndex % 5) == 4) { %>
</div>
<div>
<% } %>
which honestly isn't very nice.
Alternatively, you could use MoreLINQ's Batch method to batch your items up into IEnumerables of 5, and then use two nested repeaters to render them. Set the outer repeater to wrap the inner repeater in <div> tags, and set the inner repeater's DataSource='<%# Container.DataItem %>'. This should result in much cleaner markup.

You can try below, I mistakenly said ListView, actually I meant DataList
<asp:DataList ID="DataList1" runat="server" RepeatColumns="5"
RepeatDirection="Horizontal" RepeatLayout="Flow">
<ItemTemplate >
<%--Your Item Data goes here--%>
</ItemTemplate>
</asp:DataList>

You may use nested Data controls (i.e Repeater) and also handle the OnItemDataBound event to bind the inner Repeater.
Sample Data Source component:
public class Item
{
public int ID { get; set; }
public string Name { get; set; }
public static List<List<Item>> getItems()
{
List<Item> list = new List<Item>()
{
new Item(){ ID=11, Name="A"},
new Item(){ ID=12, Name="B"},
new Item(){ ID=13, Name="C"},
new Item(){ ID=14, Name="D"},
new Item(){ ID=15, Name="E"},
};
/* Split the list as per specified size */
int size = 2;
var lists = Enumerable.Range(0, (list.Count + size - 1) / size)
.Select(index => list.GetRange(index * size,
Math.Min(size, list.Count - index * size)))
.ToList();
return lists;
}
}
Markup (.aspx)
<asp:Repeater ID="outerRepeater"
runat="server" onitemdatabound="outerRepeater_ItemDataBound"
>
<ItemTemplate>
<p>
Row
</p>
<asp:Repeater ID="innerRepeater"
runat="server">
<ItemTemplate>
<asp:Literal ID="literal1" runat="server" Text='<%# Eval("ID") %>' />
<asp:Literal ID="literal2" runat="server" Text='<%# Eval("Name") %>' />
</ItemTemplate>
</asp:Repeater>
</ItemTemplate>
</asp:Repeater>
Code-behind
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
outerRepeater.DataSource = Item.getItems();
outerRepeater.DataBind();
}
}
protected void outerRepeater_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
Repeater repeater = e.Item.FindControl("innerRepeater") as Repeater;
repeater.DataSource = Item.getItems()[e.Item.ItemIndex];
repeater.DataBind();
}

<asp:Repeater ID="Repeater1" runat="server"
OnItemDataBound="Repeater1_databinding">
<HeaderTemplate>
<table id="masterDataTable" class="reportTable list issues" width="100%">
<thead>
<tr>
<asp:Literal ID="literalHeader" runat="server"></asp:Literal>
</tr>
</thead>
<tbody>
</HeaderTemplate>
<ItemTemplate>
<tr>
<asp:Literal ID="literals" runat="server"></asp:Literal>
</tr>
</ItemTemplate>
<FooterTemplate>
</tbody> </table>
</FooterTemplate>
</asp:Repeater>
<input id="hdnColumnName" runat="server" clientidmode="Static" type="hidden" />
<input id="hdnColumnOrder" runat="server" clientidmode="Static" type="hidden" />
// javascript Function
<script type="text/javascript">
$(document).ready(function () {
$('#ddlReport').removeClass('required');
$('.sort').click(function () {
$('#hdnColumnName').val($(this).text());
$('#hdnColumnOrder').val($(this).attr('class'));
$(this).toggleClass("desc asc");
$("#lnkSort").click();
});
});
</script>
// Bind repeater
DataTable dt = objReport.GetCustomRecord();
fn = new List<string>();
for (int i = 0; i < dt.Columns.Count; i++)
{
if (dt.Columns[i].ColumnName != "Maxcount" )
{
fn.Add(dt.Columns[i].ColumnName);
}
}
Repeater1.DataSource = dt;
Repeater1.DataBind();
protected void Repeater1_databinding(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Header)
{
if (e.Item.FindControl("literalHeader") != null)
{
StringBuilder sb = new StringBuilder();
Literal li = e.Item.FindControl("literalHeader") as Literal;
fieldName().ForEach(delegate(string fn)
{
if (hdnColumnName.Value != fn.ToString())
{
sb.Append("<th width=\"10%\"> <a id=\"btnCustomerName\" class=\"sort desc\" onclick=\"btnSorts_onclick()\" style=\"cursor:pointer;text-decoration: none !important;\" >"
+ fn.ToString() + "</a></th>");
}
else
{
if (hdnColumnOrder.Value == "sort asc")
sb.Append("<th width=\"10%\"> <a id=\"btnCustomerName\" class=\"sort desc\" onclick=\"btnSorts_onclick()\" style=\"cursor:pointer;text-decoration: none !important;\" >"
+ fn.ToString() + "</a></th>");
else
sb.Append("<th width=\"10%\"> <a id=\"btnCustomerName\" class=\"sort asc\" onclick=\"btnSorts_onclick()\" style=\"cursor:pointer;text-decoration: none !important;\">"
+ fn.ToString() + "</a></th>");
}
});
li.Text = sb.ToString();
}
}
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
if (e.Item.FindControl("literals") != null)
{
DataRowView drv = (DataRowView)e.Item.DataItem;
Literal li = e.Item.FindControl("literals") as Literal;
StringBuilder sb = new StringBuilder();
fieldName().ForEach(delegate(string fn)
{
sb.Append("<td>" + drv[fn.ToString()] + "</td>");
});
li.Text = sb.ToString();
}
}
}

Related

Problems with Radio button in the datalist

Guys before asking this questions I did a lot of research on this topic but I am not able to detect the problem.I have radio button in the datalist and I am trying to get the selected radio button value.But it is showing me false for all radio button on submit button.My datalist is like this:
<asp:DataList ID="dlEmails" RepeatLayout="Flow" runat="server" >
<HeaderTemplate>
<table>
<tr>
<th>Select Email Address </th>
<th>Status</th>
</tr>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td>
<asp:RadioButton ID="rbtnSelect" Text='<%#Eval("Emails") %>' onclick='fnrad(this);' GroupName="a" Checked='<%#Eval("Primary") %>' runat="server" /><br />
(<asp:Label ID="lablel" runat="server" Text='<%#Eval("Verified") %>'> </asp:Label>)
</td>
<td valign="middle">
<asp:Label ID="lblID" Style="display: none;" runat="server" Text='<%#Eval("Id") %>'> </asp:Label>
<asp:Label ID="Label1" runat="server" Text='<%#Eval("Main") %>'> </asp:Label>
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:DataList>
Javascript for allowing only single radio button selection at a time is like this:
<script>
function fnrad(rbtn) {
var radioList = document.getElementsByTagName("input");
for (var i = 0 ; i < radioList.length; i++) {
if (radioList[i].type == "radio") {
radioList[i].name = 'a';
radioList[i].checked = false;
}
}
rbtn.checked = true;
rbtn.setAttribute("Checked","checked");
}
</script>
And my code behind is like this:
public partial class Member_EmailList : System.Web.UI.Page
{
EmailsBAL _mbl = new EmailsBAL(SessionContext.SystemUser);
DataSet _ds = new DataSet();
URLMessage URLMessage = new URLMessage();
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
LoadData();
}
}
private void LoadData()
{
_mbl.LoadByUser(_ds, 1);//SessionContext.SystemUser;
dlEmails.DataSource = _ds.Tables[_mbl.SqlEntityX];
dlEmails.DataBind();
}
protected void lnkConfirm_Click(object sender, EventArgs e)
{
RadioButton rb;
Label lbl;
int id = 0;
foreach (DataListItem di in dlEmails.Items)
{
rb = (RadioButton)di.FindControl("rbtnSelect");
if (rb.Checked == true)
{
lbl = (Label)di.FindControl("lblID");
id = WebHelper.Cast(lbl.Text, 0);
}
}
//Response.Redirect("~/Member/ConfirmEmail.aspx?" + URLMessage.Encrypt("SystemUser=" + SessionContext.SystemUser + "Id=" + id.ToString()));
}}
I tried your javascript function and experienced your problem
I would like to suggest to use Jquery on your javascript function. I refactored your jav fuction to this.
function fnrad(rbtn) {
$('input').removeAttr('checked');
$(rbtn).prop('checked', true);
}
This works perfectly on my end. Please let me know if you still encountering the issue.

Fill megamenu dynamically

I have this functions that gets categories in three levels.
One that gets ParentCategories
One that gets categories by ParentCategoryID
One that gets Subcategories by categoriesID.
I want to build a megamenu looking like this site:
http://www.potterybarn.com/
HTML Markup
<div>
<asp:Repeater ID="HorizMenuRepeater" runat="server">
<HeaderTemplate>
<ul id="mega-menu"></HeaderTemplate>
<ItemTemplate>
<li><a id="mBox" href="javascript:;">'<%#Eval("ParentCatName")%>'</a></li></ItemTemplate>
<FooterTemplate></ul></FooterTemplate></asp:Repeater>
</div>
<script>
window.addEvent('domready', function () {
new mBox.Tooltip({
content: 'MegamenuUC',
setStyles: { content: { padding: 15, lineHeight: 20 } },
position: {
x: 'right',
y: 'bottom'
},
attach: 'mBox',
closeOnMouseleave: true
});
});
</script>
<div id="MegamenuUC" style="display:none">
<uc1:Megamenu ID="Megamenu1" runat="server" />
</div>
result
Code of the usercontrol
<ul>
<h3>Category</h3>
<ul>
<li>Sub category</li>
</ul>
</ul>
I want to make this dynamically, now it's just the parentcategory that is dynamic.
I need somehow pass the id to know witch parentcategory you hovered over tho pas the right id to my function that gets the categories so I can populate my usercontrol with it
Thanks
I solved it and i used a repeater to create a clean list and a jquery plugin to create megamenu
Link to jquery plugin http://www.designchemical.com/lab/jquery-mega-drop-down-menu-plugin/options/
Code for databind repeater with linq
<div>
<asp:Repeater ID="ParentRepeater" runat="server" OnItemDataBound="ParentRepeater_OnItemBound">
<HeaderTemplate>
<ul>
</HeaderTemplate>
<ItemTemplate>
<li><a><%# DataBinder.Eval(Container.DataItem, "ParentCatName") %></a>
<asp:Repeater ID="ParentCatRepeater" runat="server" OnItemDataBound="ChildRepeater_OnItemBound">
<HeaderTemplate>
<ul>
</HeaderTemplate>
<ItemTemplate>
<li><a><%# DataBinder.Eval(Container.DataItem, "CategoryName") %></a>
<asp:Repeater ID="ChildRepeater" runat="server">
<HeaderTemplate>
<ul>
</HeaderTemplate>
<ItemTemplate>
<li><a><%# DataBinder.Eval(Container.DataItem, "ProductName") %></a></li>
</ItemTemplate>
<FooterTemplate></ul></FooterTemplate>
</asp:Repeater>
</li>
</ItemTemplate>
<FooterTemplate></ul></FooterTemplate>
</asp:Repeater>
</li>
</ItemTemplate>
<FooterTemplate></ul></FooterTemplate>
</asp:Repeater>
</div>
C#
protected void Page_Load(object sender, EventArgs e)
{
LinqtoDBDataContext db = new LinqtoDBDataContext();
ParentRepeater.DataSource = db.GetParentCategories();
ParentRepeater.DataBind();
}
protected void ParentRepeater_OnItemBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
dynamic cat = e.Item.DataItem as dynamic;
int parentcatid = Convert.ToInt32(cat.ParentCatID);
LinqtoDBDataContext db = new LinqtoDBDataContext();
//var cats = from c in db.Categories
// where c.ParentCatID == parentcatid
// select c;
Repeater ParentCatRepeater = e.Item.FindControl("ParentCatRepeater") as Repeater;
ParentCatRepeater.DataSource = db.GetCategories(parentcatid);
ParentCatRepeater.DataBind();
}
}
protected void ChildRepeater_OnItemBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
dynamic prod = e.Item.DataItem as dynamic;
int catid = Convert.ToInt32(prod.CategoryID);
LinqtoDBDataContext db = new LinqtoDBDataContext();
Repeater ChildRepeater = e.Item.FindControl("ChildRepeater") as Repeater;
ChildRepeater.DataSource = db.GetProductsInCategory(catid);
ChildRepeater.DataBind();
}
}
}

listview databind alphabetical order

I need to order my Category titles -
( <%#Eval("CategoryDescription").ToString().ToUpper()%> )
Alphabetically. How do I do this? Thanks!
Here is the code behind in C#:
protected void lstvwFileCategory_OnItemDataBound(Object sender,
ListViewItemEventArgs e)
{
if (e.Item.ItemType == ListViewItemType.DataItem)
{
ListViewDataItem temp = (ListViewDataItem)e.Item;
Files.HAHADocument_Category catdata =
(Files.HAHADocument_Category)temp.DataItem;
ListView files = new ListView();
files = (ListView)e.Item.FindControl("lstvwFiles");
files.DataSource = catdata.Documents;
files.DataBind();
}
}
Here is the code itself:
<asp:ListView runat="server" ID="lstvwFileCategory"
OnItemDataBound="lstvwFileCategory_OnItemDataBound">
<LayoutTemplate>
<asp:Literal runat="server" ID="itemPlaceholder" />
</LayoutTemplate>
<ItemTemplate>
<div class="linksection">
<h2><%#Eval("CategoryDescription").ToString().ToUpper()%></h2>
<asp:ListView runat="server" ID="lstvwFiles"
OnItemDataBound="lstdvwFiles_OnItemDataBound">
<LayoutTemplate>
<asp:Literal runat="server" ID="itemPlaceholder" />
</LayoutTemplate>
</div>
</ItemTemplate>
</asp:ListView>
and
if (PageID > 0)
{
HAHA_BLL.FileRepository.Files fls = new HAHA_BLL.FileRepository.Files();
lstvwFileCategory.DataSource =
fls.GetHAHADocument_Categories((int)PageID);
lstvwFileCategory.DataBind();
}
Add using System.Linq; at the top of the code behind file, then change the data source assignment to this:
lstvwFileCategory.DataSource = fls.GetHAHADocument_Categories((int)PageID)
.OrderBy(c => c.CategoryDescription);

Want Checked Item From Listview

I am working with listview in C# webapplication. My Problem is I want checked Items from the listview . I have try with find selecteditem and all. I dont know how to get checked items from checkbox inside listview.My code is as follows:-
aspx
<asp:ListView ID="PackagesListView" runat="server" DataSourceID="PackagesDataSource" ItemPlaceholderID="itemPlaceholder"
GroupItemCount="4" GroupPlaceholderID="groupPlaceholder" OnItemDataBound="PackagesListView_ItemDataBound">
<LayoutTemplate>
<table style="margin-left:0px; width:570; table-layout:fixed; overflow:hidden;">
<tr ID="groupPlaceholder" runat="server" >
</tr>
</table>
</LayoutTemplate>
<GroupTemplate>
<tr class="productsTableRow">
<td ID="itemPlaceholder" runat="server"></td>
</tr>
</GroupTemplate>
<ItemTemplate>
<td style="width:140px;">
<div style="text-align:center; line-height:1.5;"><asp:Label ID="PackageLabel" runat="server" Text='<%#Eval("Name")%>' /></div>
<div style="text-align:center;"><asp:CheckBox ID="PackageCheckBox" runat="server" OnCheckedChanged="OnPackageSelected" AutoPostBack="true" PackageID='<%#Eval("PackageID")%>' /></div>
</td>
</ItemTemplate>
</asp:ListView>
<asp:Button ID="ButtonSaveQuotation" runat="server" Text="Save Quotation"
CssClass="button" Visible="false" onclick="ButtonSaveQuotation_Click1" />
aspx.cs
protected void ButtonSaveQuotation_Click1(object sender, EventArgs e)
{
StringBuilder sb = new StringBuilder();
}
so here in sb I want to append text of all the label whose checkboxes are checked.Thank You
You will have to find the checkbox since it's inside the template field
Example:
if (PackagesListView.Items.Count > 0)
{
for (int i = 0; i < PackagesListView.Items.Count; i++)
{
CheckBox PackageCheckBox= (CheckBox)PackagesListView.Items[i].FindControl("PackageCheckBox");
if (PackageCheckBox!= null)
{
if (PackageCheckBox.Checked.Equals(true))
{
//do your stuff here
}
}
}
}
foreach (var item in PackagesListView.Items.Where(i => ((CheckBox)i.FindControl("PackageCheckBox")).Checked))
{
var label =(Label) item.FindControl("PackageLabel");
label.Text += " Appended text";
}
Perhaps this will help you? This should go after page load. Also make sure you are not rebinding your listview.
var texts = PackagesListView.Items.Cast<Control>()
.Where(c => ((CheckBox)c.FindControl("PackageCheckBox")).Checked)
.Select(c => ((Label)c.FindControl("PackageLabel")).Text);
var sb = new StringBuilder();
foreach ( var text in texts)
sb.AppendLine(text);

Display message in repeater when no row found

I am using ASP.NET repeater and I want to display No Row Found message when query return 0 rows from database. I know its there in GridView.
Regards
If you have a HeaderTemplate or a FooterTemplate defined, you could add any HtmlControl or ServerControl inside of either of them and then programatically show/hide it in the codebehind.
<asp:Repeater id="Repeater1" runat="server" OnItemDataBound="">
<HeaderTemplate>
<h1>My Repeater Data</h1>
<div id="NoRecords" runat="server" visible="false">
No records are available.
</div>
</HeaderTemplate>
<ItemTemplate>
...
</ItemTemplate>
</asp:Repeater>
Here's the code behind
protected void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (Repeater1.Items.Count < 1)
{
if (e.Item.ItemType == ListItemType.Header)
{
HtmlGenericControl noRecordsDiv = (e.Item.FindControl("NoRecords") as HtmlGenericControl);
if (noRecordsDiv != null) {
noRecordsDiv.Visible = true;
}
}
}
}
Think about using the ListView control instead that has an EmptyDataTemplate for use when the data source has no data. If you opt to stick with the Repeater control, think about testing your query for records and optionally displaying a Label or Literal that has your "no row found" message instead of your repeater.
if (query.Any())
{
repeater.DataSource = query;
repeater.DataBind();
}
else
{
noRecordsLiteral.Visible = true;
}
Here is a simple example to demonstrate Displaying No Record Found in a Repeater control.
<div id="NoRecords" runat="server" visible="false">
No records are available.
</div>
<asp:Repeater id="Repeater1" runat="server" OnPreRender="Repeater1_PreRender">
<HeaderTemplate>
<h1>My Repeater Data</h1>
</HeaderTemplate>
<ItemTemplate>
...
</ItemTemplate>
</asp:Repeater>
Here is the Code-Behind
protected void Repeater1_PreRender(object sender, EventArgs e)
{
if (Repeater1.Items.Count < 1)
{
NoRecords.Visible = true;
Repeater1.Visible = false;
}
}
You could do this by altering the logic in the repeater or by providing data to the repeater that drives the behavior you want. I prefer that the repeater is left out of it. It's a keep your logic out of the view thing if you are familiar with MVC.
I am saving space here by using a List as the data source instead of a database result but the principle is the same. You would probably have a collection of IDataRecord as your source if you are returning from a DB.
using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Collections.Generic;
using System.Linq;
namespace StackOverflowRepeater
{
public partial class Default : System.Web.UI.Page
{
protected override void OnInit(EventArgs e)
{
repeater.ItemDataBound += HandleRepeaterItemDataBound;
var data = new List<string>();
if (!data.Any()) // could also be data.Count < 1
{
data.Add("No Row Found");
}
repeater.DataSource = data;
repeater.DataBind();
base.OnInit(e);
}
void HandleRepeaterItemDataBound (object sender, RepeaterItemEventArgs e)
{
if ((e.Item.ItemType == ListItemType.AlternatingItem) || (e.Item.ItemType == ListItemType.Item))
{
var span = (HtmlGenericControl) e.Item.FindControl("output");
span.InnerText = e.Item.DataItem.ToString();
}
}
}
}
This is assuming the following mark-up:
<%# Page Language="C#" Inherits="StackOverflowRepeater.Default" %>
<html>
<body>
<form runat="server">
<asp:Repeater id='repeater' runat="server">
<ItemTemplate>
<span id='output' runat="server" />
</ItemTemplate>
</asp:Repeater>
</form>
</body>
</html>
I done something following;
<asp:Repeater ID="Repeater" runat="server">
<HeaderTemplate>
<table>
<% if (Repeater.Items.Count < 1)
{ %>
<tr>
<td colspan="3">No data found.</td>
</tr>
<% }
else { %>
<tr>
<th>Case Id</th>
<th>Claim Id</th>
<th>Notes</th>
</tr>
<% } %>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td rowspan="2"><%# Eval("CaseId") %></td>
<td rowspan="2">
<%# Eval("ClaimId") %>
</td>
<td><%# Eval("Note") %></td>
</tr>
<tr>
<td><%# Eval("CreatedBy") %> : <%# Eval("CreatedDate") %></td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
You can also do it like this:
CSS
.div-no-display {
display: none;
}
Code Behind - Usually don't bind it if its empty in that case you have to put the div outside the repeater, but if you bind 0 items you can put it in the header template
this.Repeater.DataSource = ChildLinksList;
this.Repeater.DataBind();
public List<Link> ChildLinksList { get; set; }
Page
<HeaderTemplate>
<div id="NoRecords" class='<%= ChildLinksList.Count > 0 ? "div-no-display" : "" %>'>
No child links active.
</div>
</HeaderTemplate>

Categories