I have a form with containing a datalist which is bound to a datasource which contains a list of items and a true/false flag. If true, the myCheck checkbox is checked:
<form id="myForm" runat="server">
<asp:Button ID="save" runat="server" Text="Save" OnClick="save_Click" />
<br />
<asp:DataList runat="server" id="myList" onitemdatabound="myList_ItemDataBound">
<HeaderTemplate>
<th>Item Name</th>
<th id="thCheck" runat="server">Check?</th>
</HeaderTemplate>
<ItemTemplate>
<td id="tdName" runat="server"><%# Eval("Name") %></td>
<td runat="server"><asp:CheckBox id="myCheck" runat="server" Checked="false" /></td>
</ItemTemplate>
</asp:DataList>
On clicking save, I want to see which items have been checked. I am using the following to iterate through the items in the datalist:
protected void save_Click(Object sender, EventArgs e)
{
String Name;
Boolean omit;
foreach (DataListItem item in myList.Items)
{
CheckBox omitCheck = (CheckBox)item.FindControl("myCheck");
if (omitCheck != null)
{
if (omitCheck.Checked == true) // This line is my problem!!
{
// do stuff
}
break;
}
}
FindControl appears to work ok and returns a checkbox, however the value is always false, even if I have checked some of the boxes. If I set the value of the checkboxes to True in the aspx page, omitCheck.Checked is always true. ViewState is not disabled.
I'm new to this so sure there is an obvious answer.
what does the myList_ItemDataBound function look like? I suspect it needs a !IsPostback to not override entered values on the postback
Related
I have 8 items in a SQL table with a Description, ItemNumber, and ImagePath.
protected void Page_Load(object sender, EventArgs e)
{
//fill the datalist for the Signs Table
string tCallFrom = "Program." + System.Reflection.MethodBase.GetCurrentMethod().Name;
string tQry = #"SELECT * FROM [js_Signs]";
DataTable tblSigns = objCommMethods.fReturnTableFromQry(clsDBSelect.enumDBSelect.ProjectMaster, tQry, tCallFrom);
SignsList.DataSource = tblSigns;
SignsList.DataBind();
}
I am using a DataList to show all of the items along with a textbox that will allow a user to input the number of items they want:
<asp:DataList ID="SignsList" runat="server" RepeatColumns="4" CellPadding="2" Width="90%" ItemStyle-HorizontalAlign="Center">
<ItemTemplate>
<table>
<tr>
<th>
<%#DataBinder.Eval(Container.DataItem, "Description") %>
</th>
</tr>
<tr>
<th>
<%#DataBinder.Eval(Container.DataItem, "ItemNumber") %>
</th>
</tr>
<tr>
<td>
<asp:Image ID="SignImage" runat="server" ImageUrl='<%#DataBinder.Eval(Container.DataItem, "ImagePath") %>' />
</td>
</tr>
<tr style="text-align: center;">
<td>
<asp:TextBox ID="txtSignQuantity" runat="server" CssClass="txtBox" BackColor="White" Enabled="true"
type="number" min="0" ToolTip="Please choose quantity of signs needed."/>
</td>
</tr>
<tr>
<td>
<p> </p>
</td>
</tr>
</table>
</ItemTemplate>
</asp:DataList>
<div class="btnGroup">
<div class="btnDiv">
<asp:Button ID="btnSave" runat="server" Text="Save" CssClass="btnSave" Width="90px" Visible="true" OnClick="btnSave_Click"/>
</div>
<div class="btnDiv">
<asp:Button ID="btnCancel" runat="server" Text="Clear" CssClass="btnCancel" Width="90px" Visible="true" OnClick="btnCancel_Click"/>
</div>
</div>
After the saved button is clicked in C# I want to find out the value that a user entered but it is always returning null:
protected void btnSave_Click(object sender, EventArgs e)
{
TextBox txtSignQuantity;
string tempSignQuantity;
try
{
foreach (DataListItem item in SignsList.Items)
{
txtSignQuantity = item.FindControl("txtSignQuantity") as TextBox;
tempSignQuantity = txtSignQuantity.Text;
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
I also checked and the Count of SignsList.Items was 8, so I know that it is retrieving the correct information. Sorry, I've never used a Data List before so I'm not really sure how to go about this...
The short answer is that data binding on postback is causing the problem. Check the Page.IsPostBack property before doing data binding:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
//fill the datalist for the Signs Table
string tCallFrom = "Program." + System.Reflection.MethodBase.GetCurrentMethod().Name;
string tQry = #"SELECT * FROM [js_Signs]";
DataTable tblSigns = objCommMethods.fReturnTableFromQry(clsDBSelect.enumDBSelect.ProjectMaster, tQry, tCallFrom);
SignsList.DataSource = tblSigns;
SignsList.DataBind();
}
}
ASP.NET WebForms attempts to abstract away the fact that the control instances that were used to render the page are not the same instances it has when handling postback events. Data binding compounds the abstraction because it has to create controls in response to the DataBind call, and then on postback, recreate them based on the ViewState it saved.
Initializing controls from ViewState happens on the Init event, so when the Load event is fired later in the page lifecycle and you call DataBind on the control, everything it restored gets wiped out and recreated.
As for why you were getting null, it may have been that the controls were wiped out but not recreated; it may have had to do with other event handlers that didn't get rewired after the second data binding.
I have a button in a ListView that when its click it opens a modal with information relevant to the button that was clicked. I was able to get the index of the current listview item but I need to get the text from a label in both the previous item and next item. Heres what I have:
protected void List_ItemCommand(object sender, ListViewCommandEventArgs e)
{
ListViewDataItem dataItem = (ListViewDataItem)e.Item;
//Gets index of Listview
int DispalyIndex = e.Item.DisplayIndex;
int ItemIndex = e.Item.DataItemIndex;
Button index = (Button)dataItem.FindControl("TitleButton");
Label Name = (Label)dataItem.FindControl("LabelName");
}
I tried decrementing the index but no luck, anyone have an idea or a better solution? Thanks.
UPDATE
Heres my listviews, I use the first Listview to get the title and then the second to pull Jobs under the title. I bind both with a query using data bind
<asp:ListView ID="List" runat="server" OnItemCommand="List_ItemCommand" OnItemDataBound="List_ItemDataBound">
<LayoutTemplate>
<table>
<tr>
<asp:PlaceHolder ID="itemPlaceholder" runat="server"></asp:PlaceHolder>
</tr>
</table>
</LayoutTemplate>
<ItemTemplate>
<span class="label label-primary"><%# Eval("LabelName")%></span> <br />
<asp:ListView ID="JobList" runat="server" ItemPlaceholderID="JobPlaceHolder" OnItemDataBound="JobList_ItemDataBound">
<LayoutTemplate>
<asp:PlaceHolder runat="server" ID="JobPlaceHolder" />
</LayoutTemplate>
<ItemTemplate>
<br />
<asp:Button runat="server" ID="TitleButton" Text='<%# Eval("Job Title") %>' Font-Size="XX-Small" Font-Bold="true" CssClass="btn-xs btn-default" ClientIDMode="Static" OnClick="TitleButton_Click" />
</ItemTemplate>
<EmptyDataTemplate>
<br />
<b> <asp:Label runat="server" Text="There is no job for this Family and Level!" /></b>
</EmptyDataTemplate>
Try this
//null check before performing an operation, dataItem might be the first element in the page
//If so, prevItem will be null
var prevItem = List.Items[itemIndex - 1].FindControl("LabelName") as Label;
//null check before performing an operation, dataItem might be the last element in the page
//If so, nextItem will be null
var lastItem = List.Items[itemIndex + 1].FindControl("LabelName") as Label;
I have a repeater on my webforms page, with a list bounded to it. while binding the list, I also attach a data-id attribute to the tr. The problem is I need to use that id in a web service call from jQuery, I am testing whether I can get the id by logging the data-id attribute value when I click on a button from the repeater item, but from the looks of things, it only logs the Item and not the Alternating item.
Button one, three and five gets log every time I click them but when I click on button two and button four, nothing gets logged in the console. See code below.
Repeater Template
<asp:Repeater runat="server" ID="rptList" OnItemDataBound="rptList_OnItemDataBound">
<HeaderTemplate>
<table>
</HeaderTemplate>
<ItemTemplate>
<tr runat="server" id="trList">
<td runat="server" id="tdList"></td>
<td runat="server" id="tdBtnRemove">
<asp:Button runat="server" ID="btnRemove" CssClass="btnRemove" Text="Remove" OnClientClick="return false;"/></td>
</tr>
</ItemTemplate>
<AlternatingItemTemplate>
<tr runat="server" id="trList">
<td runat="server" id="tdList"></td>
<td runat="server" id="tdBtnRemove">
<asp:Button runat="server" ID="btnRemove" Text="Remove" OnClientClick="return false;"/></td>
</tr>
</AlternatingItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
List item
List<string> listObj = new List<string>(){"one", "two", "three", "four", "five"};
protected void rptList_OnItemDataBound(object sender, RepeaterItemEventArgs e)
{
string listItem = (string) e.Item.DataItem;
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
HtmlTableRow trList = (HtmlTableRow)e.Item.FindControl("trList");
trList.Attributes.Add("data-id", listItem);
HtmlTableCell tdList = (HtmlTableCell)e.Item.FindControl("tdList");
tdList.InnerHtml = listItem;
}
}
jQuery button click method:
$(".btnRemove").click(function () {
var dataAttributVal = $(this).closest("tr");
var datA = dataAttributVal.data('id');
console.log(datA);
});
Console result:
As stated in the comments, your AlternatingItemTemplate misses the CssClass="btnRemove" attribute.
For this reason your $(".btnRemove").click(... binding does not target the buttons in your AlternatingItemTemplate
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 have a ASP.NET Application with a ListView. In every Row in my ListView I have a LinkButton that open a new webform "Benutzer.aspx". my Problem is that I don't get the Index of this Row. I use the ItemCommand Event but it not work :(
Here my Code:
ASPX:
...
<ItemTemplate>
<tr runat="server">
<td align="left" ><asp:Label ID="Label1" Text='<%# Eval("Benutzer") %>' runat="server" /></td>
<td align="left"><asp:Label ID="Label2" Text='<%# Eval("eMail") %>' runat="server" /></td>
<td align="left"><asp:Label ID="Label3" Text='<%# Eval("Vorname") %>' runat="server" /></td>
<td align="left"><asp:Label ID="Label4" Text='<%# Eval("Nachname") %>' runat="server" /></td>
<td align="left"><asp:Label ID="Label5" Text='<%# Eval("Telefon") %>' runat="server" /></td>
<td align="left"><asp:LinkButton runat="server" Text="Anzeigen" CommandName="Anzeigen" OnCommand="ListView1_ItemCommand" CommandArgument="myArguments"></asp:LinkButton></td>
</tr>
</ItemTemplate>
...
cs file:
...
protected void ListView1_ItemCommand(object sender, ListViewCommandEventArgs e)
{
if (e.CommandName == "Anzeigen")
{
Label lbText = (Label)e.Item.FindControl("Label2");
string email = lbText.Text;
Session["email"] = email;
Response.Redirect("Benutzer.aspx");
}
}
...
What is the matter :(
tarasov
Try this:
First you need to have the index of the button. So in the html code add this in the CommandArgument of the button to get the index:
CommandArgument='<%# Container.DataItemIndex %>'
Then in the codebehind:
if (e.CommandName == "Anzeigen")
{
Label lbText = ListView1.Item[e.CommandArgument].FindControl("Label2");
string email = lbText.Text;
Session["email"] = email;
Response.Redirect("Benutzer.aspx");
}
Hope I Helped
You cannot find the control because it is contained in the child control collection of another server control:
<tr runat="server">
You need to try to find the control recursively:
Take a look
Better way to find control in ASP.NET
Or you can use this extension method:
public static class ControlExtensions
{
public static Control FindControlRecursively(this Control control, string targetControlID)
{
if (control == null)
{
return null;
}
var ctrl = control.FindControl(targetControlID);
if (ctrl == null)
{
foreach (Control child in control.Controls)
{
ctrl = FindControlRecursively(child, targetControlID);
if (ctrl != null)
{
break;
}
}
}
return ctrl;
}
}
Usage:
var ctrl = e.Item.FindControlRecursively("your control ID");
The code you have furnished is simply fine... "just remove the 'CommandArgument' from your listview property , bcoz..its already have the dataindex you are looking for. By specifying a command argument you are overriding the default one.
So just remove the command argument and your code will work fine... :)
I am a VB programmer Check this method may b it gives you some idea
after binding the list with datasource, In the itemCommand do this
Dim <sometext> As Label = TryCast(e.Item.FindControl("Anzeigen"), Label)
If e.CommandName = "Anzeigen" Then
'do what ever you like
'also you can use <sometext> if you want to extract data from list
'simply use <sometext>.<whatproperty>, you can also store it in sessions like the email you are using.
Session("email") = email
Response.Redirect("Benutzer.aspx");
End If
let me know if it helps you solve your problem.
This is the HTML, then build the OnItemCommand.
<asp:ListView ID="lvFiles" runat="server" DataKeyNames="FileName" OnItemCommand="lvFiles_ItemCommand">
<ItemTemplate>
<tr runat="server">
<td style="width:80px">
<asp:LinkButton runat="server"
ID="SelectEmployeeButton"
Text="Download File"
CommandName='<%#Eval("FileName")%>'
CommandArgument='<%#Eval("FileName")%>' />
</td>
</tr>
</ItemTemplate>
</asp:ListView>
Here is the code behind...
protected void lvFiles_ItemCommand(object sender, ListViewCommandEventArgs e)
{
string v = e.CommandArgument.ToString();
}