Use repeater to display all the threads in same topic question - c#

I want to use asp.net repeater control to display all threads that under same topic. Each thread has three buttons--reply,edit and delete. Besides buttons, I also want to display author, subject, post time and content. I have two questions here regarding to how to write button click event and binding data to a div in backend. My front end code is as following:(I use c#)
<asp:Repeater ID="Repeater1" runat="server">
<HeaderTemplate>
<table>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td colspan="2">
<asp:Button ID="btn_Reply" runat="server" Text="Rreply" OnClick="btn_Reply_Click" />
<asp:Button ID="btn_Edit" runat="server" Text="Edit" OnClick="btn_Edit_Click" CommandArgument='<%Eval("id").ToString() %>' />
<asp:Button ID="btn_Delete" runat="server" Text="Delete" OnClick="btn_Delete_Click" CommandArgument='<%Eval("id").ToString() %>' />
</td>
</tr>
<tr>
<td align="right" width="100px">Author:</td>
<td><%#Eval("owner") %></td>
</tr>
<tr>
<td align="right" width="100px">Subject:</td>
<td><%#Eval("title") %></td>
</tr>
<tr>
<td align="right" width="100px">Post Time:</td>
<td><%#Eval("timePosted") %></td>
</tr>
<tr>
<td colspan="2">
<div id="contentDiv" runat="server" ondatabinding="contentDiv_DataBinding"></div>
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
Question 1: how to write button click event in backend, for example I want to use CommandArgument of edit button, what's the click event should be?
protected void btn_Edit_Click(object sender,??//I don't know how to write the second)
Question 2: the content stored in database is in html format, What to write in contentDiv_DataBinding event?
protected void contentDiv_DataBinding(object sender, System.EventArgs e)
{
//seems it can not find contentDiv, otherwise, I'll just use contentDiv.html=<%#Eval("content") %>
}
Thank you in advance!

As the control is nested inside the Repeater, you must refer to it by finding it inside the item being data bound:
protected void Repeater_DataBinding(object sender, System.EventArgs e)
{
HtmlControl contentDiv = e.item.FindControl("contentDiv");
}
However, I think it would be better to put a Literal control inside the Div and refer to that instead:
<div id="contentDiv" runat="server">
<asp:literal id="ltlContent" runat="server" />
</div>
protected void Repeater_DataBinding(object sender, System.EventArgs e)
{
Literal ltlContent = e.item.FindControl("ltlContent");
ltlContent = e.Item.DataItem("content");
}
Regarding controlling the buttons inside the Repeater, you can add a CommandName to the button and call this in the ItemCommand event:
<asp:Button ID="btn_Reply" runat="server" Text="Rreply" CommandName="Reply" CommandArgument='<%Eval("id")%>' />
<asp:Button ID="btn_Edit" runat="server" Text="Edit" CommandName="Edit" CommandArgument='<%Eval("id").ToString() %>' />
<asp:Button ID="btn_Delete" runat="server" Text="Delete" CommandName="Delete" CommandArgument='<%Eval("id").ToString() %>' />
protected void contentDiv_ItemCommand(object sender, System.EventArgs e)
{
if (e.CommandName == "Reply"){
}
if (e.CommandName == "Edit"){
}
if (e.CommandName == "Delete"){
}
}
Finally, change your Repeater tag to:
<asp:Repeater ID="Repeater1" runat="server" OnItemDataBound="Repeater_DataBinding" OnItemCommand="contentDiv_ItemCommand">

Related

ASP.NET (C#) - ListView

In past, i worked on ListViews (.net 2.0) using a custom Template field but what i am trying to achieve here is the following
I am now working on .net 4.6
So basically a list which shows items like above and on mouse-hover few options show up as shown in the following screenshot
I also have to trigger those option to do different things -
How can I do that in asp.net, may I please have some code references.
Cheers
P.S.
This is a rough example of how i am creating the List Item Template (as requested)
<asp:ListView ID="ListView1" runat="server" DataSourceID="SqlDataSource1">
<AlternatingItemTemplate>
<table >
<tr>
<td ><asp:Image ID="image1" ImageUrl='<%# Bind("url") %>' runat="server" Width="98px" /> </td>
<td><h2><asp:Label ID="_label" runat="server" Text ='<%# Bind("title") %>'></asp:Label></h2><asp:Label ID="Label1" runat="server" Text ='<%# Bind("description") %>'></asp:Label></td>
</tr>
</table>
</AlternatingItemTemplate>
<EmptyDataTemplate>
No data was returned.
</EmptyDataTemplate>
<ItemSeparatorTemplate>
<br />
</ItemSeparatorTemplate>
<ItemTemplate>
<table >
<tr>
<td ><asp:Image ID="image1" ImageUrl='<%# Bind("url") %>' runat="server" Width="98px" /> </td>
<td><h2><asp:Label ID="_label" runat="server" Text ='<%# Bind("title") %>'></asp:Label></h2><asp:Label ID="Label1" runat="server" Text ='<%# Bind("description") %>'></asp:Label></td>
</tr>
</table>
</ItemTemplate>
<LayoutTemplate>
<ul id="itemPlaceholderContainer" runat="server" style="">
<li runat="server" id="itemPlaceholder" />
</ul>
<div style="">
</div>
</LayoutTemplate>
</asp:ListView>
I can add any html formatting to this template e,g i can add ASP:button etc but i don't know how to trigger those to perform certain tasks.
One easy way to achieve your requirement is to keep those buttons there but invisible and show them up when the parent container is hovered. following as a quick sample
aspx
<asp:ListView ID="ListView1" runat="server">
<ItemTemplate>
<tr class="row-data">
<td>
<asp:Label ID="NameLabel" runat="server" Text='<%# Eval("Name") %>' />
</td>
<td>
<asp:Label ID="PositionLabel" runat="server" Text='<%# Eval("Position") %>' />
</td>
<td>
<div class="btn-area">
<asp:Button runat="server" Text="Button1" />
<asp:Button runat="server" Text="Button2" />
</div>
</td>
</tr>
</ItemTemplate>
<LayoutTemplate>
<table id="itemPlaceholderContainer" runat="server" border="0" style="">
<tr runat="server" style="">
<th runat="server">
Name
</th>
<th runat="server">
Position
</th>
<th>
</th>
</tr>
<tr id="itemPlaceholder" runat="server">
</tr>
</table>
</LayoutTemplate>
</asp:ListView>
css
.btn-area
{
display: none;
}
.row-data:hover .btn-area
{
display: block;
}
code-behind
protected void Page_Load(object sender, EventArgs e)
{
ListView1.DataSource = new List<dynamic>() {
new { Name = "Andy", Position = "PG"},
new { Name = "Bill", Position = "SD"},
new { Name = "Caroline", Position = "Manager"}
};
ListView1.DataBind();
}
UPDATE
ListView ItemCommand can capture the postback by button pressed and CommandName makes you able to recognize which button fired it.
<asp:Button runat="server" Text="Button1" CommandName="c1" />
<asp:Button runat="server" Text="Button2" CommandName="c2" />
code-behind
protected void ListView1_ItemCommand(object sender, ListViewCommandEventArgs e)
{
if (e.CommandName == "c1")
{
// do something when button1 pressed
}
else if (e.CommandName == "c1")
{
// do something when button2 pressed
}
}

How to access Listview items to codebehind using asp.net

Iam using a listview to display table contents,How can i access a values form listview to code behind in button click
aspx
<LayoutTemplate>
<table runat="server" id="table1">
<tr id="Tr1" runat="server">
<th class="tablehead"id="mname">Movie Name</th>
<th class="tablehead">Movie Genre</th>
<th class="tablehead">Runtime</th>
</tr>
<tr runat="server" id="itemPlaceholder"></tr>
<ItemTemplate>
<tr id="Tr2" runat="server" class="tablerw">
<td style="background-color:#EEEEEE;width:100px;" class="tablerw"><asp:Label ID="Label5" runat="server" Text='<%#Eval("MovieName") %>' /></td>
<td style="background-color:#EEEEEE;width:100px;"><asp:Label ID="NameLabel" runat="server" Text='<%#Eval("movieGenre") %>' /></td>
<td style="background-color:#EEEEEE;width:100px;"><asp:Label ID="Label1" runat="server" Text='<%#Eval("Runtime") %>' /></td>
<td>
<asp:Button ID="Button1" runat="server" Text="Approve" OnClick="Button1_Click"></asp:Button>//Here is my button
</ItemTemplate>
aspx.cs
protected void Button1_Click(Object sender,
System.EventArgs e)
{
//I want to access value here
}
I want to get Movie Name,Movie Genre,Runtime to code behind.. Any help is appreciated..
Proper way to deal with button control click event in data bound controls is by setting a CommandArgument & CommandName properties. Instead of registering a click handler of button you can register a ItemCommand event of ListView. This way whenever a button is clicked then this event is raised and you can find the data correctly like this:-
Add CommandName & CommandArgument properties to your button and remove the click handler:-
<asp:Button ID="Button1" runat="server" Text="Approve" CommandName="GetData"
CommandArgument='<%# Eval("MovieId") %>' ></asp:Button>
Next, register the ItemCommand event with your listview:-
<asp:ListView ID="lstMovies" runat="server" OnItemCommand="ListView1_ItemCommand">
Finally in the code behind, in ListView1_ItemCommand method check if event is raised by your button and find all the respective controls:-
protected void ListView1_ItemCommand(object sender, ListViewCommandEventArgs e)
{
if (e.CommandName == "GetData")
{
if (e.CommandSource is Button)
{
ListViewDataItem item = (e.CommandSource as Button).NamingContainer
as ListViewDataItem;
Label NameLabel = item.FindControl("NameLabel") as Label;
Label Label5 = item.FindControl("Label5") as Label;
//and so on..
}
}
}

How to get items row id of repeater when user clicks rows linkbutton control

I have a repeater, nested with Html table rows:
<asp:Repeater ID="Repeater1" runat="server" OnItemDataBound="Repeater1_ItemDataBound">
<HeaderTemplate>
<table id="grid">
<thead>
<tr>
<th>SID</th>
<th>Start Date</th>
<th>End Date</th>..
<th>PDF Text</th>
</tr>
</thead>
<tbody>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td><%#DataBinder.Eval(Container.DataItem,"ID") %></td>
<td><%#DataBinder.Eval(Container.DataItem,"startDate") %></td>
<td><%#DataBinder.Eval(Container.DataItem,"endDate") %></td
<td>
<asp:LinkButton runat="server" ID="lbtnPDF" Text="PDF Full Text" OnClick="lbtnPDF_Click" />
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</tbody>
</table>
</FooterTemplate>
</asp:Repeater>
When the user clicks on linkbutton, I want to get the ID of that row of repeater item and will display the PDF file which is related to that ID, in another aspx page.
I wrote on itemdatabound event :
protected void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
LinkButton lnkBtn = (LinkButton)e.Item.FindControl("lbtnPDF");
}
How can I get column Id of repeater nested with an html table?
I don't think you are following the right approach to do it. I would choose the benefits of Repeater's ItemCommand Event to do it.
The following code might be helpful to you:
HTML/ASP.net
<asp:Repeater ID="Repeater1" DataSourceID="SqlDataSource1" runat="server" OnItemCommand="Repeater1_ItemCommand">
<ItemTemplate>
<asp:Button ID="Button1" runat="server" Text='<%#DataBinder.Eval(Container.DataItem,"Username") %>' CommandName="ViewPDF" CommandArgument='<%#DataBinder.Eval(Container.DataItem,"ID") %>' />
</ItemTemplate>
</asp:Repeater>
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString='<%$ ConnectionStrings:myConnString %>' SelectCommand="SELECT * FROM [tblUserAccounts]"></asp:SqlDataSource>
As you have noticed, I have used CommandName and CommandArgument attributes in the label. I have used CommandName attribute to identify which action the user is expecting. Also the CommandArgument to pass the required data object to server.
Go to Repeater's OnItemCommand instead of ItemDataBound event. And write the code as below;
protected void Repeater1_ItemCommand(object source, RepeaterCommandEventArgs e)
{
if (e.CommandName == "ViewPDF")
{
Response.Redirect("~/MyPDFFiles/" + (string)e.CommandArgument);
}
}
Now run and test your Application!
Hope this helps!

Dynamic Link Button OnClick event not firing

I am creating several dynamic asp:Panels in asp:Lisview ItemTemplate. In panel there's a HTML table which is surrounded by link so the whole div/box is clickable. The problem is the linkbutton's OnClick event is not firing on server side. Any thoughts?
Here is the code:
<asp:Panel runat="server" ClientIDMode="Static">
<asp:LinkButton runat="server" ID="Link" OnClick="Link_Click" CausesValidation="false">
<table runat="server" id="Table" >
<thead>
<tr><th colspan="3"><%#Eval("abc")%></th></tr>
</thead>
<tbody>
<tr>
<td >
<asp:ImageButton runat="server" ImageUrl="../Images/img_4.png"/>
</td>
<td runat="server" class="data" >
<%#Eval("abc")%>
</td>
<td>
04:15
</td>
</tr>
</tbody>
</table>
</asp:LinkButton>
</asp:Panel>
LinkClick Code
protected void Link_Click(object sender, EventArgs e)
{
LinkButton link = (LinkButton)sender;
String id = link.ID;
if (id.StartsWith("T"))
Response.Redirect("Time.aspx?Id=" + id);
else
{
Response.Redirect("Chart.aspx?Id=" + id);
}
}
I figured it out. The asp:linkbutton id was being reset in the backend code and it was leading to broken link. That's why the click wouldn't work.

How to Edit data in nested Listview

I am using listview to display a list of items and a nested listview to show list of features to each item. Both parent and child listview need to able Insert,Edit and delete operation. It works fine for parent listview. But when I try to edit an child item, The edit button does not take it into Edit mode. Can you please suggest me what I am missing in my code?
<asp:ListView ID="lvParent" runat="server"
OnItemDataBound="lvParent_ItemDataBound"
onitemcanceling="lvParent_ItemCanceling" onitemcommand="lvParent_ItemCommand"
DataKeyNames="ItemID" onitemdeleting="lvParent_ItemDeleting"
oniteminserting="lvParent_ItemInserting" >
<LayoutTemplate>
<asp:PlaceHolder ID="itemPlaceholder" runat="server"></asp:PlaceHolder>
<div align="right">
<asp:Button ID="btnInsert" runat="server" Text="ADD Item" onclick="btnInsert_Click"/>
</div>
</LayoutTemplate>
<ItemTemplate>
<table runat="server" cellpadding="0" cellspacing="0" border="0" width="100%">
<tr>
<td>
<div id="dvDetail">
<span >Description</span>
<asp:TextBox ID="txtDescription" runat="server" Text='<%# DataBinder.Eval(Container.DataItem, "Description") %>' TextMode="MultiLine" ></asp:TextBox>
</div>
<div id="dvFeature" >
<span>Feature List</span>
<asp:ListView ID="lvChild" runat="server"
InsertItemPosition="LastItem"
DataKeyNames="FeatureID" OnItemCommand="lvChild_ItemCommand"
OnItemCanceling="lvChild_ItemCanceling" OnItemDeleting="lvChild_ItemDeleting"
OnItemEditing="lvChild_ItemEditing" OnItemInserting="lvChild_ItemInserting" OnItemUpdating="lvChild_ItemUpdating"
DataSource='<%# DataBinder.Eval(Container.DataItem, "FeatureList") %>' >
<LayoutTemplate>
<ul >
<asp:PlaceHolder runat="server" ID="itemPlaceHolder" ></asp:PlaceHolder>
</ul>
</LayoutTemplate>
<ItemTemplate>
<li>
<span class="dvList"><%# DataBinder.Eval(Container.DataItem, "FeatureTitle")%></span>
<div class="dvButton" >
<asp:ImageButton ID="btnEdit" runat="server" ImageUrl="/Images/edit_16x16.gif" AlternateText= "Edit" CommandName="Edit" CommandArgument='<%# DataBinder.Eval(Container.DataItem, "FeatureID") %>' Width="12" Height="12" />
<asp:ImageButton ID="btnDelete" runat="server" ImageUrl="/Images/delete_16x16.gif" AlternateText= "Delete" CommandName="Delete" CommandArgument='<%# DataBinder.Eval(Container.DataItem, "FeatureID") %>' Width="12" Height="12" />
</div>
</li>
</ItemTemplate>
<EditItemTemplate>
<li>
<asp:TextBox ID="txtFeature" Text='<%# DataBinder.Eval(Container.DataItem, "FeatureTitle")%>' runat="server"></asp:TextBox>
<div class="dvButton">
<asp:ImageButton ID="btnUpdate" runat="server" ImageUrl="/Images/ok_16x16.gif" AlternateText= "Update" CommandName="Update" CommandArgument='<%# DataBinder.Eval(Container.DataItem, "FeatureID") %>' Width="12" Height="12" />
<asp:ImageButton ID="btnCancel" runat="server" ImageUrl="/Images/delete_16x16.gif" AlternateText= "Cancel" CommandName="Cancel" Width="12" Height="12" CausesValidation="false" />
</div>
</li>
</EditItemTemplate>
<InsertItemTemplate>
<asp:TextBox ID="txtFeature" runat="server"></asp:TextBox>
<div class="dvButton">
<asp:ImageButton ID="btnInsert" runat="server" ImageUrl="/Images/ok_16x16.gif" AlternateText= "Insert" CommandName="Insert" Width="12" Height="12" />
<asp:ImageButton ID="btnCancel" runat="server" ImageUrl="/Images/delete_16x16.gif" AlternateText= "Cancel" CommandName="Cancel" Width="12" Height="12" CausesValidation="false" />
</div>
</InsertItemTemplate>
</asp:ListView>
</div>
</td>
</tr>
<tr>
<td align="right">
<div id="dvButton" >
<asp:Button ID="btnSave" runat="server" Text="Save"
CommandName="Save"
CommandArgument='<%# DataBinder.Eval(Container.DataItem, "ItemID") %>' />
<asp:Button ID="btnDelete" runat="server" Text="Delete" CssClass="Cancel"
CommandName="Delete"
CommandArgument='<%# DataBinder.Eval(Container.DataItem, "ItemID") %>' />
</div>
</td>
</tr>
</table>
</ItemTemplate>
</asp:ListView>
Code Behind:
protected void Page_Load(object sender, EventArgs e)
{
if (Page.IsPostBack == false)
{
BindData();
}
}
private void BindData()
{
MyDataContext data = new MyDataContext();
var result = from itm in data.ItemLists
where itm.ItemID == iItemID
select new
{
itm.ItemID,
itm.Description,
FeatureList = itm.Features
};
lvParent.DataSource = result;
lvParent.DataBind();
}
protected void lvChild_ItemEditing(object sender, ListViewEditEventArgs e)
{
ListView lvChild = sender as ListView;
lvChild.EditIndex = e.NewEditIndex;
lvChild.DataBind();
}
Edit:
protected void lvChild_ItemEditing(object sender, ListViewEditEventArgs e)
{
ListView lvChild = sender as ListView;
lvChild.EditIndex = e.NewEditIndex;
lvChild.DataBind();
}
If I use "lvChild.DataBind()" in 'ItemEditing' event, the total list of child items goes away if I click 'edit'
protected void lvChild_ItemEditing(object sender, ListViewEditEventArgs e)
{
ListView lvChild = sender as ListView;
lvChild.EditIndex = e.NewEditIndex;
}
if I get rid of 'lvChild.Databind' in ItemEditing event, it goes to Edit mode after clicking the 'edit' button twice . And though it shows textbox control of EditItemTemplate, it appears as a blank textbox (does not bind existing value to edit).
This is an interesting problem. Almost certainly a databinding issue. In order to enter edit mode you must do two things:
1) Set the EditIndex
2) Call DataBind()
In the case of nested repeaters though... when does Render get called? I suspect you will have to call DataBind() on the PARENT in order to render everything correctly. That being the case you may have to then set the EditIndex AGAIN, since you are rebinding the parent.
EDIT:
OK... I just tried this with a nested GridView and I did NOT have to DataBind() the parent to get the sub grid to enter edit mode. Now I have to downvote my own answer. :|
hope that will serve someone, somewhere.
Here is my code to get that to work:
1) I have a Listview wich hold a user control when editing. This User cotnrol has itself a listview inside
<asp:ListView runat=server ID=C_LV_MyObjects DataKeyNames="Id"
OnItemDataBound=DataBoundMyObjects OnItemEditing=ItemEditing
>
<LayoutTemplate>
<table runat=server id="itemPlaceholderContainer">
<tr>
<th>
Description
</th>
</tr>
<tr runat="server" id="itemPlaceholder">
</tr>
</table>
</LayoutTemplate>
<ItemTemplate>
<tr>
<td>
text...
</td>
<td>
<asp:LinkButton runat="server" CommandName="Edit" Text="Edit"></asp:LinkButton>
</td>
<td>
<asp:LinkButton runat="server" CommandName="Delete" Text="Delete"></asp:LinkButton>
</td>
</ItemTemplate>
<EditItemTemplate>
<tr>
<td colspan=3>
<MyTag:MyUC ID=C_UC_MyUserControl runat=server
OnEditing=MyObjectEditing
/>
</td>
</tr>
</EditItemTemplate>
<EmptyDataTemplate>
No results found!
</EmptyDataTemplate>
</asp:ListView>
The code c# for this listview is as follows :
public int EditIndexComposition;
protected void ItemEditing(object sender, ListViewEditEventArgs e)
{
C_LV_MyObjects.EditIndex = e.NewEditIndex;
C_LV_MyObjects.DataBind();
}
protected void MyObjectEditing(object sender, EventArgs e)
{
ListViewEditEventArgs MyEvent = (ListViewEditEventArgs)e;
if (MyEvent != null)
EditIndexComposition= MyEvent.NewEditIndex;
C_LV_MyObjects.DataBind();
}
protected void DataBoundMyObjects(object sender, ListViewItemEventArgs e)
{
MyUC uc = (MyUC)e.Item.FindControl("C_UC_MyUserControl");
if (uc!=null)
{
uc.EditIndex = EditIndexComposition;
ListViewDataItem dataItem = (ListViewDataItem)e.Item;
MyObject obj= (MyObject)dataItem.DataItem;
uc.DataSource=Myservice.GetDatasource(obj.Id);
uc.DataBind();
}
}
and the code of my Usercontrol is as follows :
<asp:PlaceHolder runat="server" ID="C_PH_ObjComposition">
<asp:ListView runat="server" ID="C_LV_AppaltatoreComposizione" DataSource="<% # DataSource %>"
DataKeyNames="Id" OnItemEditing="ItemEditing">
etc...
<ItemTemplate>
<tr>
<td>
<asp:LinkButton runat="server" CommandName="Edit" Text="Edit"></asp:LinkButton>
</td>
</tr>
</ItemTemplate>
<EditItemTemplate>
<tr>
<td>
Edit Mode
</td>
</tr>
</EditItemTemplate>
</asp:ListView>
</asp:PlaceHolder>
with the following code c# :
public int EditIndex
{
get {return C_LV_ObjComposition.EditIndex;}
set { C_LV_ObjComposition.EditIndex=value;}
}
public event EventHandler Editing;
protected void ItemEditing(object sender, ListViewEditEventArgs e)
{
C_LV_ObjComposition.EditIndex = e.NewEditIndex;
if (Editing != null)
Editing(this, e);
}
When clicking on the edit button of the innerlistview, we store the index that was clicked and we trigger a function in the first container user control. This function is going to store in a global value the index cliked and triggers a databind of the outter list. Doing so we get the onitemdatabound, that will recreate our usercontrol with the proper values, we can then before the databinding of the usercontrol assign the index of the editing row.
That's all if you have any questions , please feel free to answer..
ciao!

Categories

Resources