C# asp.net - Repeaters Collections of text boxes - c#

Assume that I have a list of the following:
First Name Last Name
Bob Wonder
Helen Wood
..., ....,
I can use a repeater and bind the source to this in asp.net but I am doing this as follows:
<asp:TextBox ID="txtName" runat="server" EnableVIewState="true" Text='<%# Eval("Name") %>'></asp:TextBox>
<asp:TextBox ID="txtLstNumber" runat="server" EnableVIewState="true" Text='<%# Eval("LastName") %>'></asp:TextBox>
Then I just bind these from a list of contacts. The problem that I am having is that I need to update the records in XML which looks like the following:
<Contact name="Bob" lastName="wonder">
The problem that I am having is that I do not understand how I would associate the two text boxes so that they relate to each other so then I can just update the XML? For example, if "Bob" changed his last name, I would then update "Bob" in the XML?

You need some Field/Column of your data as primary key or ID, like numbers 1,2,.. and these are not going to change.
However, for just updating contacts, will use the contact index as identification.
Markup:
<%# Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html>
<html>
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<asp:Repeater ID="repeater1" runat="server" OnItemDataBound="repeater1_ItemDataBound">
<HeaderTemplate>
<table>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td>
Name
</td>
<td>
<asp:TextBox ID="txtName" runat="server" />
</td>
<td>
Last name
</td>
<td>
<asp:TextBox ID="txtLstNumber" runat="server" />
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table></FooterTemplate>
</asp:Repeater>
<asp:Button ID="SaveButton" runat="server" Text="Save"
onclick="SaveButton_Click" />
</form>
</body>
</html>
CS
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Xml;
using System.IO;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack) readxml();
}
private void readxml()
{
var xmldoc = new XmlDocument();
xmldoc.Load(Server.MapPath("contacts.xml"));
var xmlnodes = xmldoc.GetElementsByTagName("Contact");
repeater1.DataSource = xmlnodes;
repeater1.DataBind();
xmldoc = null;
}
protected void repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType != ListItemType.Item && e.Item.ItemType != ListItemType.AlternatingItem) return;
var node = (XmlNode)e.Item.DataItem;
var txtName = (TextBox)e.Item.FindControl("txtName");
txtName.Text = node.Attributes["name"].Value;
var txtLstNumber = (TextBox)e.Item.FindControl("txtLstNumber");
txtLstNumber.Text = node.Attributes["lastName"].Value;
}
protected void SaveButton_Click(object sender, EventArgs e)
{
var xmldoc = new XmlDocument();
xmldoc.Load(Server.MapPath("contacts.xml"));
var xmlnodes = xmldoc.GetElementsByTagName("Contact");
for (var i = 0; i < repeater1.Items.Count; i++)
{
var item = repeater1.Items[i];
var txtName = (TextBox)item.FindControl("txtName");
var name = txtName.Text ;
var txtLstNumber = (TextBox)item.FindControl("txtLstNumber");
var lastName = txtLstNumber.Text;
var node = xmlnodes[i];
node.Attributes["name"].Value = name;
node.Attributes["lastName"].Value = lastName;
}
xmldoc.Save(Server.MapPath("contacts.xml"));
xmldoc = null;
}
}
XML file
<?xml version="1.0" encoding="utf-8"?>
<root>
<Contact name="bob" lastName="jan" />
<Contact name="john " lastName="doe" />
</root>

Related

Set checkbox as checked in Repeater/CheckboxList

I'm using a Repeater to show some data coming from a web service.
My Repeater structure is:
<asp:Repeater ID="rptgrp" runat="server">
<ItemTemplate>
<asp:CheckBoxList ID="chkBoxListGoup" runat="server"
DataSource='<%# DataBinder.Eval(Container.DataItem, "Titles")%>'
DataTextField="Title"
DataValueField="IDTitle">
</asp:CheckBoxList>
</ItemTemplate>
</asp:Repeater>
Now, my web service returns these fields in "Titles":
1) Title
2) IDTitle
3) isUserTitle
Now, I would like to set checked a checkbox when isUserTitle is = 1.
How can I do that?
You can find checkboxlist as follows
Find checkboxlist in itemdatabound,
check item text of every checkboxlist using loop,
select the item whose text is 1
Protected void Repeater_ItemDataBound(Object Sender, RepeaterItemEventArgs e) {
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
CheckBoxList chklst = (CheckBoxList)e.Item.FindControl("chkBoxListGoup");
for (int i = 0; i < chk.Items.Count; i++)
{
if (chk.Items[i].Text == "1")
{
chk.Items[i].Selected = true;
}
}
}
}
Try changing <asp:CheckBoxList ID="chkBoxListGoup" runat="server"
to
<asp:CheckBoxList ID="chkBoxListGoup" Checked='<%#Eval("Flag")%>' runat="server"
Flag being your Column..
Then in your method or event handler you want to run some code to say if this value = 1 checked, elseif value = 0 unchecked...
Here is sample code that demonstrates the idea:
Code-behind:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.UI.WebControls;
using WebApp.RepeaterCheckboxList.TODODatasetTableAdapters;
namespace WebApp.RepeaterCheckboxList
{
public partial class WebForm1 : System.Web.UI.Page
{
IEnumerable<TODODataset.TasksViewRow> view;
IEnumerable<TODODataset.TasksViewRow> subview;
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
TasksViewTableAdapter adp = new TasksViewTableAdapter();
var dt = adp.GetData();
view = dt.AsEnumerable();
var names = (from x in view
select new
{
Person = x.Name,
ID = x.PersonID
}).Distinct();
DataList1.DataSource = names;
DataList1.DataBind();
}
}
protected void CheckBoxList1_DataBound(object sender, EventArgs e)
{
CheckBoxList theList = (CheckBoxList)sender;
var person = ((DataListItem)theList.Parent).DataItem as dynamic;
var name = person.Person;
var id = person.ID;
var vw = subview;
for (int i = 0, j = vw.Count(); i < j; i++)
{
var task = vw.ElementAt(i);
theList.Items[i].Selected = task.Completed;
}
}
protected IEnumerable<TODODataset.TasksViewRow> GetTasks(object data)
{
var vw = data as dynamic;
return subview = (from x in view
where x.PersonID == vw.ID
select x);
}
}
}
Aspx:
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="WebApp.RepeaterCheckboxList.WebForm1" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:DataList ID="DataList1" runat="server">
<ItemTemplate>
<div style="padding:5px">
<h3><%# Eval("Person") %></h3>
<div>
<asp:CheckBoxList OnDataBound="CheckBoxList1_DataBound" ID="CheckBoxList1"
runat="server"
DataTextField="TaskDesc" DataValueField="TaskID"
DataSource="<%# GetTasks(Container.DataItem) %>"></asp:CheckBoxList>
</div>
</div>
</ItemTemplate>
</asp:DataList>
</div>
</form>
</body>
</html>
If you are interested in the data, click here
Try just setting the Checked value to the object being Evaled.
<asp:Repeater ID="rptgrp" runat="server">
<ItemTemplate>
<asp:CheckBoxList ID="chkBoxListGoup" runat="server"
Checked=<%# Eval("isUserTitle") %>>
</asp:CheckBoxList>
</ItemTemplate>
</asp:Repeater>

asp.net C# - DataList2 Refresh based on the value of DataList1

I am new to ASP.NET and C#. I want to refresh the 2nd DataList (DataList2) when a user clicks on the (+) sign.
Datalist1 will list all Company records with a column that has a (+) sign. If a user clicks the (+), it will expand (DataList2) below the company and list all the contact names.
Please help. Thanks!
<%# Page Language="C#" AutoEventWireup="true" CodeFile="CompanyList.aspx.cs" Inherits="_CompanyList" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<link id="Link1" rel="stylesheet" runat="server" media="screen" href="/Apps/ERP/ERP_Styles.css" />
</head>
<body>
<form id="form1" runat="server">
<table style="width:100%" border="0">
<tr>
<td style="width:20%"></td>
<td style="width:60%">
<p class="PageTitle">Company List</p>
</td>
<td style="width:20%">
<asp:Button ID="myBtn" runat="server" Text="Click me"
OnClientClick="window.parent.location.href='/Apps/ERP/ASPX/UploadContact/UploadContact.aspx'; return false;" />
</td>
</tr>
</table>
<%-- ////////////////////////////////////// Start Data Row ///////////////////////////////////////// --%>
<table width="595px">
<asp:DataList BackColor="#ffffff" id="DataList1" DataSourceID="dsCompanyList" runat="server" Width="100%">
<ItemTemplate>
<tr>
<td>
<asp:LinkButton ID="LinkButton1" runat="server" Text="+" CommandArgument='<%#Container.ItemIndex%>'
OnCommand="LinkButton1_Command"
></asp:LinkButton>
</td>
<td><%#Eval("Row")%></td>
<td><%#Eval("Company")%></td>
</tr>
<asp:Panel ID="pnlChildView" runat="server">
<asp:DataList ID="DataList2" runat="server" Width="100%">
<ItemTemplate>
<tr>
<td><%#Eval("FirstName")%></td>
<td><%#Eval("LastName")%></td>
</tr>
</ItemTemplate>
</asp:DataList>
</asp:Panel>
</ItemTemplate>
</asp:DataList>
</table>
<asp:SqlDataSource ID="dsCompanyList" runat="server"
ConnectionString="<%$ ConnectionStrings:ConnApps %>"
SelectCommand="SELECT ROW_NUMBER() OVER (ORDER By MatchFlag ASC) AS ROW
, Company FROM (
SELECT DISTINCT(Company) AS Company, MatchFlag
--,InsertFlag, MatchFlag
FROM dbo.Import_CompanyContact icc
WHERE RefNum = #RefNum
AND MatchFlag = 2
) a "
>
<SelectParameters>
<asp:QueryStringParameter Name="RefNum" QueryStringField="RefNum" DefaultValue="0" Type="Int16" />
</SelectParameters>
</asp:SqlDataSource>
</form>
</body>
</html>
The code behind .cs file
using System;
using System.Collections.Generic;
//using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class _CompanyList : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void LinkButton1_Command(object sender, CommandEventArgs e)
{
//pass index of item in command argument
int itemIndex = Convert.ToInt32(e.CommandArgument);
//depending on your needs bind the details on demand
//or preload during ItemDataBound
Panel childViewPanel = (Panel)DataList1.Items[itemIndex].FindControl("pnlChildView");
if (childViewPanel != null)
{
//toggle visibility of childViewPanel and bind child list if panel is visible
if (childViewPanel.Visible)
{
DataList childList = (DataList)childViewPanel.FindControl("DataList2");
if (childList != null)
{
int keyValue = (int)DataList1.DataKeys[itemIndex];
//bind the list using DataList1 data key value
childList.DataSource = "SELECT FirstName, LastName FROM dbo.Import_CompanyContact WHERE Company = 'Applied Micro'"; //get data using keyValue
childList.DataBind();
}
}
}
}
}
There are a few things needed to make this work for you, but first - please consider using stored procedures or at least parameterized queries.
You are attempting to access the .DataKeys of the "parent" DataList but you never included that on your definition. In order to accurately do this, you're going to need to change your source query to include some key value (instead of just ROW_NUMBER() (not a key) and Company):
<asp:DataList BackColor="#ffffff"
id="DataList1"
DataSourceID="dsCompanyList"
runat="server"
Width="100%"
DataKeyField="YourKeyField">
Then, you'll need to alter your code-behind to set the .DataSource of your "child" DataList...and while I'm using your query, please consider using something other than dynamic SQL:
protected void LinkButton1_Command(object sender, CommandEventArgs e)
{
int itemIndex = Convert.ToInt32(e.CommandArgument);
Panel childViewPanel = (Panel)DataList1.Items[itemIndex].FindControl("pnlChildView");
if (childViewPanel != null)
{
if (childViewPanel.Visible)
{
DataList childList = (DataList)childViewPanel.FindControl("DataList2");
if (childList != null)
{
int keyValue = (int)DataList1.DataKeys[itemIndex];
using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["YourConnectionString"].ConnectionString))
{
con.Open();
using (SqlCommand cmd = new SqlCommand("SELECT FirstName, LastName FROM dbo.Import_CompanyContact WHERE Company = " + keyValue, con))
{
cmd.CommandType = CommandType.Text;
using (SqlDataReader dr = cmd.ExecuteReader())
{
childList.DataSource = dr;
childList.DataBind();
}
}
}
}
}
}
}

Make Datalist items link-able in asp.net

I want to make Datalist with linkable items that I can Navigate to specific url when i click on it it go to c# do respond to new URL
My Urls aren't constant
how?
you should edit the item template of the DataList and put an ASP HyperLink inside, and you use data binding to assign the NavigateUrl to such control.
something like this:
<asp:DataList ID="listSearchResults" Border="1" BorderColor="Black"
RepeatDirect="Horizontal" RepeatColumns="5" runat="server" >
<ItemTemplate>
<asp:HyperLink ID="HyperLink1" runat="server" NavigateUrl='<%# Eval("Url") %>' Text='<%# Eval("Name") %>' />
</ItemTemplate>
</asp:DataList>
another approach is to use ASP:LinkButton and assign CommandName and CommandArgument properties to that control.
<%# Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org /TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Datalist with linkable items</title>
</head>
<body>
<form id="form1" runat="server">
<div align="center">
<asp:DataList ID="dlLinkable" runat="server"
onitemdatabound="dlLinkable_ItemDataBound" >
<ItemTemplate>
<table style="width: 300px;" cellpadding="0" cellspacing="1">
<tr>
<td style="width:200px">
<asp:Label ID="lblName" runat="server" Text="Label"></asp:Label>
</td>
<td>
<a id="linkA" runat="server">link</a>
</td>
</tr>
</table>
</ItemTemplate>
</asp:DataList>
</div>
</form>
</body>
</html>
using System;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
public partial class _Default : System.Web.UI.Page
{
DataTable dt;
protected void Page_Load(object sender, EventArgs e)
{
populateDataList();
}
private void populateDataList()
{
dt = new DataTable();
//Create 3 columns for this DataTable
DataColumn col1 = new DataColumn("ID");
DataColumn col2 = new DataColumn("Name");
DataColumn col3 = new DataColumn("Url");
//Add All These Columns into DataTable table
dt.Columns.Add(col1);
dt.Columns.Add(col2);
dt.Columns.Add(col3);
// Create a Row in the DataTable table
DataRow row = dt.NewRow();
row[col1] = 1;
row[col2] = "google";
row[col3] = "http://www.google.com";
dt.Rows.Add(row);
//////////////////////
row = dt.NewRow();
row[col1] = 2;
row[col2] = "yahoo";
row[col3] = "http://www.yahoo.com";
dt.Rows.Add(row);
//////////////////////////////////
dlLinkable.DataSource = dt;
dlLinkable.DataBind();
}
protected void dlLinkable_ItemDataBound(object sender, DataListItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.AlternatingItem || e.Item.ItemType == ListItemType.Item)
{
Label lblName = (Label)e.Item.FindControl("lblName");
if (lblName != null)
{
lblName.Text = dt.Rows[e.Item.ItemIndex]["Name"].ToString();
}
HtmlAnchor linkA = (HtmlAnchor)e.Item.FindControl("linkA");
if (linkA != null)
{
linkA.HRef = dt.Rows[e.Item.ItemIndex]["Url"].ToString();
}
}
}
}

advancing to button code-behind when validation fails... how to solve it without Page.IsValid?

I have an ASP .NET page with both asp .net validators and some javascript checking too.
I am advancing into the button code behind:
protected void Button2_Click(object sender, EventArgs e)
{
if (Page.IsValid)
{
/// ...
Even when the validation fails!
The Page.IsValid check solves it, but it also resets all the JavaScript variables… May there be a way not to advance into the button code?
I have an ajax update panel and some image buttons on the page too… Anything I may look out for?
Thanks in advance!
Here is my aspx:
<%# Page Language="C#" AutoEventWireup="true"
CodeBehind="WebForm2.aspx.cs"
Inherits="WebForm2" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div style="width: 500px;">
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<script type="text/javascript">
var nrOptions = 0;
alert(nrOptions + " - variable initialized");
function IncrementQuantity() {
nrOptions++;
alert(nrOptions);
}
function DecrementQuantity() {
nrOptions--;
alert(nrOptions);
}
function MoreThanTwo() {
alert(nrOptions);
if (nrOptions > 1) {
alert('okay - you have: ' + nrOptions);
return true;
}
else {
alert('error - must have at least two options, you only have: ' + nrOptions);
return false;
}
}
</script>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:Repeater ID="Repeater1" runat="server" OnItemCommand="Repeater1_ItemCommand">
<HeaderTemplate>
Fill in with two or more options:<br />
<table border="1" width="100%">
</HeaderTemplate>
<ItemTemplate>
<tr>
<td valign="middle">
</td>
<td valign="middle">
Description:
<asp:TextBox ID="TBox1" runat="server" Width="120px" Text='<%# Eval("Desc")%>'></asp:TextBox>
<asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" ControlToValidate="TBox1"
ValidationGroup="InsertVal" ErrorMessage="*"></asp:RequiredFieldValidator>
Points:
<asp:TextBox ID="TBox2" runat="server" Width="20px" Text='<%# Eval("Pont")%>'></asp:TextBox>
<asp:RequiredFieldValidator ID="RequiredFieldValidator2" runat="server" ControlToValidate="TBox2"
ValidationGroup="InsertVal" ErrorMessage="*"></asp:RequiredFieldValidator>
<asp:Button ID="ImageButton1" runat="server" Text="x" CommandName="DeleteRow" OnClientClick="DecrementQuantity();" />
<asp:RegularExpressionValidator ID="RegularExpressionValidator1" ControlToValidate="TBox2"
ValidationExpression="\d+" ValidationGroup="InsertVal" runat="server"
ErrorMessage="Number >= 0."></asp:RegularExpressionValidator>
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
<tr>
<td colspan="2" align="right">
<asp:Button ID="lnkAddRow" runat="server" Text="Add option" OnClientClick="IncrementQuantity();"
CommandName="AddRow" OnClick="lnkAddRow_Click" />
</td>
</tr>
</table>
</FooterTemplate>
</asp:Repeater>
<br />
<p style="text-align: right;">
<asp:Button ID="Button2" runat="server" Text="Save" OnClick="Button2_Click" OnClientClick="return MoreThanTwo();"
ValidationGroup="InsertVal" />
</p>
</ContentTemplate>
</asp:UpdatePanel>
</div>
</form>
</body>
</html>
And my code-behind:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;
public partial class WebForm2 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!this.IsPostBack)
{
DTable = EmptyDTOptions();
Repeater1.DataSource = DTable;
Repeater1.DataBind();
}
}
protected void Repeater1_ItemCommand(object source, RepeaterCommandEventArgs e)
{
if (e.CommandName == "AddRow")
{
DTable.Rows.Add(0, "", "");
Repeater1.DataSource = DTable;
Repeater1.DataBind();
return;
}
if (e.CommandName == "DeleteRow")
{
int idx = e.Item.ItemIndex;
DTable.Rows.RemoveAt(idx);
Repeater1.DataSource = DTable;
Repeater1.DataBind();
return;
}
}
protected void lnkAddRow_Click(object sender, EventArgs e)
{
foreach (RepeaterItem item in Repeater1.Items)
{
int idx = item.ItemIndex;
TextBox tb1 = (TextBox)item.FindControl("TBox1");
TextBox tb2 = (TextBox)item.FindControl("TBox2");
DTable.Rows[idx]["Desc"] = tb1.Text;
DTable.Rows[idx]["Pont"] = tb2.Text;
}
}
protected void Button2_Click(object sender, EventArgs e)
{
if (Page.IsValid)
{
// save!
}
}
private DataTable DTable
{
get
{
DataTable _dt = (DataTable)Session["DTable"];
if (Object.Equals(_dt, null))
{
_dt = EmptyDTOptions();
Session.Add("DTable", _dt);
}
return _dt;
}
set
{
Session["DTable"] = value;
}
}
DataTable EmptyDTOptions()
{
DataTable dt = new DataTable();
DataColumn dc;
dc = new DataColumn("OptionNr", System.Type.GetType("System.Int32"));
dt.Columns.Add(dc);
dc = new DataColumn("Desc");
dt.Columns.Add(dc);
dc = new DataColumn("Pont");
dt.Columns.Add(dc);
return dt;
}
}
I think it shows what I'm trying to avoid... Advancing to the button2_click with the failed validation (and resetting the javascript variable)... In order to get a list of two or more pairs of items, one of them being a number.
Rather than calling your function from the OnClientClick on the button, you can add a CustomValidator that calls your JavaScript function.
<asp:CustomValidator ID="CheckMoreThanTwo" runat="server"
ValidationGroup="InsertVal"
ClientValidationFunction="MoreThanTwo" />
Then, modify your JavaScript function as follows:
function MoreThanTwo(source, arguments) {
alert(nrOptions);
if (nrOptions > 1) {
alert('okay - you have: ' + nrOptions);
arguments.IsValid=true;
} else {
alert('error - must have at least two options, you only have: '
+ nrOptions);
arguments.IsValid=false;
}
}
Doing this allows your custom JavaScript validation to work with all the validation code that ASP.NET uses. For instance, if you change to a validation summary, or change validation groups, this custom validator will continue to work the way the rest of the validators work.

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