ASP.NET Repeater need to alter display - asp.net

I have the following Repeater:
<asp:Repeater ID="rpttsk" runat="server">
<HeaderTemplate>
<tr>
<td>
<b>ID</b>
</td>
<td>
<b>Date</b>
</td>
</tr>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td>
<%#Eval("ID")%>
</td>
<td>
<%#Eval("PerfDate", "{0:MMM d, yyyy}")%>
</td>
</tr>
</ItemTemplate>
</asp:Repeater>
I am putting the code in the code behind file
Protected Sub rpttsk_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.RepeaterItemEventArgs) Handles rpttsk.ItemDataBound
but not even hitting this sub procedure

I'd do it this way:
Frontend:
<asp:Repeater ID="rpttsk" runat="server" OnItemDataBound="rpttsk_ItemDataBound">
<HeaderTemplate>
<tr>
<td>
<b>ID</b>
</td>
<td>
<b>Date</b>
</td>
</tr>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td>
<%#Eval("ID")%>
</td>
<td>
<asp:Label ID="lbl" runat="server"/>
</td>
</tr>
</ItemTemplate>
</asp:Repeater>
Backend:
protected void rpttsk_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.AlternatingItem || e.Item.ItemType == ListItemType.Item)
{
YourDataType item = e.Item.DataItem as YourDataType;
Label lbl = e.Item.FindControl("lbl") as Label;
lbl.Text = item;
if (DateTime.Compare(item.YourDateHere, DateTime.Now()) > 0)
{
lbl.ForeColor = Color.Red;
}
else
{
lbl.ForeColor = Color.Blue;
}
}
}
If you want entire rows to be coloured, you'll have to put everything in labels.

You can set this logic in code Behind in ItemDataBound
void rpttsk_ItemDataBound(Object Sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
}
}

Choosing the colour to display is a view concern. In general I would put view concern logic into the views rather than the code behinds. It allows for more view flexibility. It can make maintenance easier since cosmetic updates to your applications don't require as many binary updates.
You could technically say that the logic of comparing the date to today is a business logic concern, possibly. So that could be a code behind thing, such as a getter like "IsDateGreaterThanToday".
Then your repeater view could be revised like so:
<td <%# IsViewGreaterThanToday(Eval("PerfDate")) ? "class='greater-than-today'" : ""%>>
<%#Eval("PerfDate", "{0:MMM d, yyyy}")%>
</td>

Related

Next textbox disable in ASP.net

I want to add one validation like if Status is "Accept" then QtyRejected get disable
Below is my ASP code for status and qtyRejected
<td>
<asp:DropDownList ID="lAccept" runat="server" Height="25px" Width="102px">
<asp:ListItem>Accept</asp:ListItem>
<asp:ListItem>Reject</asp:ListItem>
</asp:DropDownList>
</tr>
<tr>
<td width="30%">
<b>Qty Rejected:</b>
</td>
<td>
<asp:TextBox ID="lRejectedQty" runat="server" CausesValidation="True"></asp:TextBox>
<%-- <asp:CustomValidator ID="CustomValidator1" runat="server"
ErrorMessage="Only interger between 1 to 10000000 " ondisposed="Page_Load"
oninit="Page_Load" onservervalidate="CustomValidator1_ServerValidate"></asp:CustomValidator>--%>
</td>
</tr>
protected void Page_Load(object sender, EventArgs e)
{
if (Page.IsPostBack)
{
if (lAccept.SelectedItem.Text == "Accept")
{
lRejectedQty.Enabled = false;
}
}
}
You should be able to retrieve the selected value of the dropdownlist using jQuery with something like this.
$('#<%= lAccept.ClientID %> option:selected').val();
Then you can disable your textbox with a little more jQuery with something like this.
$('#<%=lRejectedQty.ClientID %>').attr("disabled", "disabled");
And if you want to re-enable.
$('#<%=lRejectedQty.ClientID %>').removeAttr("disabled");
Hope this helps.

wont display drop down

<form>
<asp:Repeater id="rptComments" runat="server">
<HeaderTemplate>
<table class="detailstable FadeOutOnEdit">
<tr>
<th style="width:200px;">Answers</th>
</tr>
</HeaderTemplate>
<ItemTemplate>
<tr>
<th style="width:200px;"><asp:DropDownList ID="dropDownForChecklistAnswers" runat="server" /></th>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
<asp:Button id="button" text="Submit" OnClick="Page_Load" runat="server" />
</FooterTemplate>
</asp:Repeater>
</form>
Code Behind:
List<Checklist_Record_Choice> CLRC =
(from choice in db.Checklist_Record_Choices
select choice).ToList();
dropDownForChecklistAnswers.DataSource = CLRC;
DropDownList1.DataTextField = Text;//Text being the name of column2 in the table (which contains yes, no, n/a)
dropDownForChecklistAnswers.DataBind();
ERROR: dropDownForChecklistAnswers does not exist in the current context???
please advise
EDIT;
thanks for reply. I have
public void OnReptDataBound(object sender, RepeaterItemEventArgs e)
{
ClarkeDBDataContext db1 = new ClarkeDBDataContext();
List<string> CLRC =
(from choice in db1.Checklist_Record_Choices
select choice.Text).ToList();
DropDownList ddl = (DropDownList)e.Item.FindControl("dropDownForChecklistAnswers");
ddl.DataSource = CLRC;
}
but DropDownList ddl is coming back as object ref not set to instance of an object...why is it null??
You need to use FindControl to access a control which is part of a Repeater's template.
Subscribe to the OnItemDataBound of the Repeater (set the attribute OnItemDataBound="OnReptDataBound")
And then in your code behind do the following
void OnReptDataBound(object sender, RepeaterItemEventArgs e)
{
if(e.Item.ItemType == ListItemType.Item)
{
DropDownList ddl = (DropDownList )e.Item.FindControl("dropDownForChecklistAnswers");
ddl.DataSource = ....

Accessing a button in a repeater from Code Behind (C#)

I am finding some serious problems in accessing a button placed in a repeater from code behind.
This is the repeater code:
<asp:Repeater ID="Repeater1" runat="server">
<HeaderTemplate></HeaderTemplate>
<ItemTemplate>
<table>
<tr>
<td>Username:</td>
<td> <%# Eval("UserName") %></td>
</tr>
<tr>
<td>Date:</td>
<td><%# Eval("CommentTime") %></td>
</tr>
<tr>
<td>Comment:</td>
<td><%# Eval("Comment") %></td>
</tr>
<tr>
<td>
<asp:Button ID="btnDeleteComment" runat="server" Text="Delete" /></td>
</tr>
</table>
<br />
</ItemTemplate>
</asp:Repeater>
And This is the code Behind placed int the page load:
Button btn = new Button();
btn = (Button)Repeater1.FindControl("btnDeleteComment");
btn.Visible = false;
Am I missing something?
Thanks
I am sure, I've solved your problem as to why you are getting the object reference not set.
As you have this conditional statement, if (e.Item.ItemType == ListItemType.Item), when its first iterates it will be a header item type. Since your your button is in the item template, that's doesn't exist in the Header template.
protected void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item)
{
Button btn = new Button();
btn = (Button)e.Item.FindControl("btnDeleteComment");
btn.Visible = false;
}
}
You can't find the control like this. What you need to do is attach an event to repeater "item data bound event" and in that event handler do:
(Button)e.Item.FindControl("btnDeleteComment");
on .aspx
<asp:Button ID="btnDeleteComment" runat="server" Text="Delete" Visible='<# IsAuthor?"true":"false" >' />
in code behind
//global scope
public bool IsAuthor=false;
//in pageload event
IsAuthor= GetIsAuthor();

nested repeater show data that matches parent repeater

I am using a repeater to build a custom table. However, I can't figure out how to make the table show subtotal if the next rows tour does not match the previous rows.
Something similar to that.
row1 tour1
row2 tour 1
tour1 subtotal
row3 tour2
row4 tour2
subtotal
total
<asp:Repeater ID="ParentRepeater" runat="server" DataSourceID="SqlDataSource1">
<HeaderTemplate>
<table border="1">
<tr>
<th>TOUR</th>
<th>THEME</th>
<th>ROUTE</th>
<th>DEPT</th>
</tr>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td><%#Container.DataItem("tour")%></td>
<td align="center"><%#Container.DataItem("theme")%></td>
<td align="right"><%#Container.DataItem("route")%></td>
<td align="right"><%#Container.DataItem("dep7")%></td>
<asp:Repeater ID="ChildRepeater" runat="server"
DataSourceID="SqlDataSource2">
<HeaderTemplate>
<table border="1">
<tr>
<th>BOOKNO</th>
<th>PARTY</th>
<th>TOUR</th>
<th>THEME</th>
<th>ROUTE</th>
<th>DEPT</th>
<th>HOME</th>
<th>USERID</th>
</tr>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td align="center"><%#Container.DataItem("bookno") %></td>
<td><%#Container.DataItem("party")%></td>
<td><%#Container.DataItem("tour")%></td>
<td align="center"><%#Container.DataItem("theme")%></td>
<td align="right"><%#Container.DataItem("route")%></td>
<td align="right"><%#Container.DataItem("dep7")%></td>
<td align="right"><%#Container.DataItem("home")%></td>
<td align="right"><%#Container.DataItem("userid")%></td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
code behind
Protected Sub ItemBound(ByVal sender As Object, ByVal args As RepeaterItemEventArgs)
If args.Item.ItemType = ListItemType.Item Then
Dim childRepeater As Repeater = DirectCast(args.Item.FindControl("ChildRepeater"), Repeater)
childRepeater.DataSource = SqlDataSource2
childRepeater.DataBind()
End If
End Sub
but this shows all the data in the nested repeater not the ones that match the parentrepeater fields
for example tour,theme,dep7 should match in the child repeater
First, add 2 class fields:
private int _subTotal; // Not sure what you're summing but you
// wrote subtotal in your pseudo-output
private int _lastTourId;
Reset these field before you databind your repeater:
_subTotal = 0;
_lastTourId = -1;
TourRepeater.DataBind();
The create a single level Repeater:
<asp:Repeater ID="TourRepeater" ...>
<HeaderTemplate>...<>
<ItemTemplate>
<tr>
Some columns with your tour data
</tr>
<PlaceHolder ID="SubTotalRow" ... />
</ItemTemplate>
<FooterTemplate>
<PlaceHolder ID="SubTotalRow" ... />
</FooterTemplate>
</asp:Repeater>
Bind this Repeater directly to your tour data, then do this in your OnItemDataBound event handler (I'll have to go for c#):
void RepeaterItemDataBound(object source, RepeaterItemEventArgs e)
{
if (
e.Item.ItemType == ListItemType.Item ||
e.Item.ItemType == ListItemType.AlternatingItem // think you forgot this
)
{
var tour = e.Item.DataItem as Tour;
if (tour != null)
{
if (_lastTourId == -1) { _lastTourId == tour.TourId; } // To avoid subtotal row before first tour
if (tour.TourId != _lastTourId) // This is a new tour so insert a subtotal row for the previous tour
{
var subTotalRow = e.Item.FindControl("SubTotalRow") as PlaceHolder;
if (subTotalRow != null)
{
RenderSummaryRow(subTotalRow, _subTotal);
}
_subTotal = tour.SomeValueYouWantToAddToSubTotal;
}
else
{
_subTotal += tour.SomValueYouWantToAddToSubTotal;
}
_lastTourId = tour.TourId;
}
}
else if (e.Item.ItemType == ListItemType.Footer)
{
var subTotalRow = e.Item.FindControl("SummaryRow") as PlaceHolder;
if (summaryTotalRow != null)
{
RenderSummaryRow(subTotalRow, _subTotal);
}
}
}
private void RenderSummaryRow(PlaceHolder placeHolder, int subTotal)
{
// create subtotal row manually by either creating TableRow + TableCells and adding them to a placeholder, or
// just add a literal and create your markup manually as innerHtml. Put your _subtotal value in where you want
}
An alternative method is to retrieve your tour data into a DataTable, and retrieve the data WITH ROLLUP etc which will create summary rows automagically. There's several tutorials about this around the web, but I couldn't find the great one I used before I switched to MVC.

How to add a <td> tag to ListViewItem?

I want to implement an apperance as this article mentioned using nested ListView control. However, in my scenario, I cannot use EntityDataSource control so I bind data manually.
My table:
Categories
PK: UniqueId, Guid
Name, string
ParentId, Guid
<asp:ListView ID="CategoryList" runat="server"
onitemdatabound="CategoryList_ItemDataBound">
<LayoutTemplate>
<table>
<asp:PlaceHolder ID="itemPlaceHolder" runat="server"></asp:PlaceHolder>
</table>
</LayoutTemplate>
<ItemTemplate>
<tr>
<td colspan="2"><%# Eval("Name") %></td>
</tr>
</ItemTemplate>
</asp:ListView>
protected void Page_Load(object sender, EventArgs e)
{
using (PractiseEntities context = new PractiseEntities()) {
var result = from categories in context.Categories
select categories;
CategoryList.DataSource = result;
CategoryList.DataBind();
}
}
I want the sub category have an indent by add a <td> tag to the item which "ParentId" is not null. And my question is how to edit the generated html tags in the ItemDataBound event?
You could have something like this:
<ItemTemplate>
<tr>
<td colspan="2"><%# GetParentContent(Eval("ParentID")) %></td>
</tr>
</ItemTemplate>
in the code-behind:
protected string GetParentContent(object ParentID)
{
if(ParentID!=null)
... return parent HTML ...
else
return "";
}

Resources