Sort of new to .NET and trying to understand how best to accomplish this task: I have a listview with a datasource containing a list of string values. The last property is some text that I'd like to place in the Text template; normally when not used inside a listview I can place markup and text inside the template successfully, so I'd like to keep this structure. But what would be a way of placing that string inside there? I've tried Databinder.Eval but as expected it says that the template doesn't contain the property I'm referring to from Container.DataItem (which becomes the template).
<asp:ListView runat="server"
ID="ListView1"
OnItemDataBound="ListView1_ItemDataBound">
<LayoutTemplate>
<div class="navigation">
<asp:PlaceHolder runat="server" id="itemPlaceholder" />
</div>
</LayoutTemplate>
<ItemTemplate>
<my:Control id="VideoLink1" runat="server">
<Text>
--- PLACE CONTENT HERE --
</Text>
</my:Control>
</ItemTemplate>
</asp:ListView>
Anyone have an idea how to accomplish this? Would be greatly appreciated.
Use ItemDatabound event of the ListView. In that find your control and then assign the desired properties.
protected void ListView1_ItemDataBound(object sender, ListViewItemEventArgs e)
{
if (e.Item.ItemType == ListViewItemType.DataItem)
{
YourControl VideoLink1= e.Item.FindControl("VideoLink1") as YourControl ;
if(VideoLink1!= null)
{
YourClass obj = ((YourClass)(((System.Web.UI.WebControls.ListViewDataItem)(e.Item)).DataItem));
VideoLink1.TextProperty = obj .TextProperty ;
}
}
}
Related
I want to hide an itemtemplate's data in listview using the td visibility property. Once I click a button it should show the data again that's within the itemtemplate. However, I cannot find the td control using c# in the code behind. Is there a way to find this control or another way to handle this?
<asp:Content runat="server" ID="BodyContent" ContentPlaceHolderID="MainContent">
<asp:Button ID="Button1" runat="server" Text="Search" OnClick="ButtonClick" />
<asp:MultiView ID="MultiView1" runat="server" ActiveViewIndex="0">
<asp:View ID="View1" runat="server">
<asp:ListView ID="SectionListView" runat="server" InsertItemPosition="FirstItem" OnPagePropertiesChanged="SectionListView_PagePropertiesChanged">
<ItemTemplate>
<tr style="">
<td></td>
<td id="row1" style="visibility:hidden;" runat="server">
<asp:Label ID="SectionItemLabel" runat="server" Text='<%# Eval("SectionItem") %>' />
</td>
</tr>
</ItemTemplate>
Here is part of the code for the button click:
protected void ButtonClick(object sender, EventArgs e)
{
var temp = (System.Web.UI.HtmlControls.HtmlTableCell)Page.Master.FindControl("MainContent").FindControl("row1");
}
You have a couple of issues. First, when you try to find "row1" within "MainContent", if won't find it because "row1" is actually a child of other children of "MainContent". It won't find them recursively unless you tell them to.
Second, since each ListViewItem within your ListView contains "row1", they are each given their own unique ID, such as SectionListView_ctrl0_row1, SectionListView_ctrl1_row1, etc. Because of this, you need to use FindControl() on each ListViewItem.
But, because you need to do it on each ListViewItem and because each ListViewItem contains "row1", each row will get the same property (i.e. all visible or all invisible). Here is how that could be done:
protected void ButtonClick(object sender, EventArgs e)
{
foreach (ListViewItem lvi in SectionListView.Items)
{
if (lvi.ItemType == ListViewItemType.DataItem)
{
HtmlTableCell row1 = (HtmlTableCell)lvi.FindControl("row1");
row1.Style.Add("visibility", "hidden");
}
}
}
If you need to style each cell individually, they would each need to be named differently. It is common to attach some sort of number or database ID to the end of the ID if that is the case.
I'm developing a ASP.NET website with a C# backend. I'm having a problem with how to set an onclick event for buttons that are nested inside of both a loginview and a repeater. The code works fine for displaying all of the other data (anonymous view displays only an error message) but right now the buttons just redirect to the same page and remove the repeater and all contents, whereas they're supposed to run a specific delete function. The repeater, as it is right now, uses an alternatingitem template. If I remove the buttons from the nested controls, they work. I've tried this with buttons, linkbuttons, and imagebuttons. I'd rather use the latter, if possible. Is it possible to assign an Onclick to these buttons if they're nested like this? If not, what approach should I use?
<asp:LoginView ID="LoginLinksView" runat="server" EnableViewState="false">
<AnonymousTemplate>
<asp:Label ID="errorlabel" runat="server"></asp:Label>
</AnonymousTemplate>
<LoggedInTemplate>
<asp:Repeater id="Repeater" runat="server" >
<HeaderTemplate>
<table cellspacing="0" cellpadding="0">
<thead></thead>
</HeaderTemplate>
<ItemTemplate>
<tr class="Repeaterrow">
<!--Additional code here-->
<asp:ImageButton ID="delbutton" runat="server" ImageUrl=
"~/Images/delete.png" Onclick="DeleteOnClick"/>
</tr>
</ItemTemplate>
<AlternatingItemTemplate>
<tr class="Repeaterrow">
<!--Additional code here-->
<asp:ImageButton ID="delbutton" runat="server" ImageUrl=
"~/Images/delete.png" Onclick="DeleteOnClick"/>
</tr>
</AlternatingItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
</LoggedInTemplate>
</asp:LoginView>
Here are the problems with your approach
1- The button issues postback as it should. But you need to put some CommandArgument with to identify "key" or which row you are processing it for.
2- Re Bind your Repeater with source. Below is the sample code for you.
protected void Page_Load(object sender, EventArgs e)
{
BindRepeater();
}
private void BindRepeater()
{
List<int> items = new List<int>();
for (int i = 0; i < 10; i++)
{
items.Add(i);
}
Repeater.DataSource = items;
Repeater.DataBind();
}
protected void DeleteOnClick(object sender, EventArgs e)
{
ImageButton delbutton = (sender as ImageButton);
//1- call your method with passing in delbutton.CommandArgument - it will give you key/ whatever you like
//2- Rebind the Repeater here and that will bind controls again...
BindRepeater();
}
protected void Repeater_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
ImageButton delbutton = (sender as RepeaterItem).FindControl("delbutton") as ImageButton;
if (delbutton != null)
{
delbutton.CommandArgument = (sender as RepeaterItem).ItemIndex.ToString();
}
}
and ASPX Repeater definition would change to
Thanks,
Riz
I have a repeater that will present a set of titles and checkboxes (some checked some not). Each is wrapped in a div with a background colour. All I want to do is change the background colour for the checkboxes that are already checked so they are easily identified on the page.
Here's the repeater:
<asp:Repeater ID="rptCartridges" runat="server" OnItemDataBound="rp_ItemDataBound">
<ItemTemplate>
<div class="cartridgebox">
<span class="cartridgeboxl"><%#Eval("cartName") %></span>
<span class="cartridgeboxr">
<asp:CheckBox ID="chkCart" name="chkbox" Checked = '<%#Convert.ToBoolean(DataBinder.Eval(Container.DataItem, "cartChecked"))%>' runat="server" />
<asp:HiddenField ID="hfCartID" runat="server" Value='<%#DataBinder.Eval(Container.DataItem, "cartID")%>' />
</span>
</div>
</ItemTemplate>
</asp:Repeater>
All I really want to do is change the class cartridgebox to cartridgeboxchecked if the checkbox is returned as checked.
I have tried manipulating rp_ItemDataBound. Where it goes wrong is the actual changing of the class inline. I've tried using if statements, add runat="server" to the div and populating a variable and then using Response.Write inside the class statement. But nothing seems to work.
What seems the neatest way would be to use rp_ItemDataBound like so:
protected void rp_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
string chkboxClass = "cartridgebox";
CheckBox chk = (CheckBox)e.Item.FindControl("chkCart");
HiddenField hfCartID = (HiddenField)e.Item.FindControl("hfCartID");
// Adding the hide.Value Attribute to the chk.Text field.
chk.Attributes.Add("Text", hfCartID.Value);
if (chk.Checked == true)
{
chkboxClass = "cartridgeboxchecked";
}
else
{
chkboxClass = "cartridgebox";
}
}
But I lack the understanding to pass the variable chkboxClass to the div's class dynamically. Of course I am probably looking at this completely wrong so any guidance would be appreciated.
Use following markup for div in ItemTemplate : <div class='<%# ((bool)Eval("cartChecked"))? "cartridgeboxchecked" : "cartridgeboxl" %>' >
If you need to change div's class on checkbox change immediatelly, consider to add onclick client-side event handler to checkbox in ItemDataBound Repeater's event handler
I have triple-nested ListView controls on my asp.net page, each nested within another. I use the OnItemDataBound event in the 1st ListView to set the DataSource of the 2nd level ListView. The 3rd ListView is contained in the of the 2nd ListView. I want to assign the same DataSource to both the 2nd and 3rd level ListView datasource controls, but I cannot figure out how to access the 3rd level ListView in order to do that.
Here is some sample code to help visualize:
<asp:ListView id="level1" runat="server" OnItemDataBound="level1_ItemDataBound">
<layouttemplate>
<asp:PlaceHolder runat="server" ID="itemPlaceHolder"></asp:PlaceHolder>
</layouttemplate>
<itemtemplate>
<asp:ListView id="level2" runat="server">
<layouttemplate>
<asp:ListView id="level3" runat="server">
<layouttemplate>
<asp:PlaceHolder runat="server" ID="itemPlaceHolder"></asp:PlaceHolder>
</layouttemplate>
<itemtemplate>OUTPUT DATA FOR LEVEL 3</itemtemplate>
</asp:ListView>
</layouttemplate>
<itemtemplate>OUTPUT DATA FOR LEVEL 2</itemtemplate>
</asp:ListView>
OUTPUT DATA FOR LEVEL 1
</itemtemplate>
</asp:ListView>
The level1_ItemDataBound method finds the level2 control, casts it as a ListView, sets its DataSource and executes the DataBind. At this point I'm stuck trying to get Level3.DataSource to be set to the same as Level2.DataSource. Any help?
Before you call DataBind on the on the level2 listview, you should register an event handler on the level2's ItemDataBound event.
Some psuedo code:
protected void level1_ItemDataBound(object sender, ListViewItemEventArgs e)
{
var listView2 = (ListView) e.Item.FindControl("level2");
listView2.ItemDataBound += level2_ItemDataBound;
listView2.DataSource = myDataSource;
listView2.DataBind();
}
protected void level2_ItemDataBound(object sender, ListViewItemEventArgs e)
{
var listView3 = (ListView) e.Item.FindControl("level3");
listView3.DataSource = myDataSource;
listView3.DataBind();
}
I have an question, On my page i have a ListView control, I also have a button that has CommandArgument. I know i can read and find a control in the ListView as :
ListView.Items[i].FindControl("controlname");
and my button in ListView is like that
asp:Button ID="WisdomButton" runat="server" CommandName="UpdateWisdom" CommandArgument='<%# need my index for Item[i] to post here %>'
OnCommand="UpdateWisdom" Text="Update" />
I want to add index value in runtime to the CommantParameter, so when i go to the Function onCommand i will know exactly from what row[i] i Need to get my controls from ListView.
So my question is, how do i dinamicly add index of ListView.Rows[i] into CommmandArgument for the Button in runtime ?
Thanks in advance.
Check out the API
http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.listviewcommandeventargs.aspx
The ListViewCommandEventArgs item has an index, IE it is already available in the argument
ListViewDataItem dataItem = (ListViewDataItem)e.Item;
int i = dataItem.DisplayIndex;
But from here you will have access to those controls
e.Item.FindConrol("controlName");
If you are calling the method a different way you could aways assign the index through an ItemDataBound Event
void MyListView_ItemDataBound(object sender, ListViewItemEventArgs e)
{
((Button)e.Item.FindControl("WisdomButton")).CommandArgument = ((ListViewDataItem)e.Item).DisplayIndex;
}
OR try something like this for giggles
<asp:Button runat="server" CommandArgument='<%# DisplayIndex %>'/>
// OR
<asp:Button runat="server" CommandArgument='<%# NextIndex() %>'/>
It might help to know a little bit more about what your are trying to do. If your end goal is to get any of the properties from your bound object you can just cast the dataItem from the ListViewCommandEventArgs of the ItemCommand event. You don't need to retain the index or call FindControl at all.
Here is an example of how to get the bound Customer object.
ListView
<asp:ListView runat="server" id="Customers" ItemCommand="Customers_ItemCommand">
<LayoutTemplate>
<ul>
<asp:placeholder runat="server" id="itemPlaceholder" />
</ul>
</LayoutTemplate>
<ItemTemplate>
<li>
<asp:Button runat="server" id="Select" CommandName="Select" />
<%# Eval("Name")%>
</li>
</ItemTemplate>
</asp:ListView>
CodeBehind
public void Page_Load()
{
if (!Page.IsPostBack)
{
this.Customers.DataSource = GetCustomers();
this.Customers.DataBind();
}
}
public void Customers_ItemCommand(object sender, ListViewCommandEventArgs e)
{
if (e.CommandName == "Select")
{
if (e.Item.ItemType != ListViewItemType.DataItem)
return;
var customer = ((ListViewDataItem)e.Item).DataItem as Customer;
if (customer != null)
{
// Now work directly with the customer object.
Response.Redirect("viewCustomer.aspx?id=" + customer.Id);
}
}
}
Edit: In addtion when you cast the item to a ListViewDataItem, then you also expose a ((ListViewDataItem)e.Item).DataItemIndex property that might help you.