Accessing Controls Inside ASP.NET View Controls (Event Handling) - asp.net

If I have the following ListView, how can I attach a SelectedIndexChanged event listener to the DropDownList so I can perform a command on the respective object? Imagine I have a list of new users and I want to add them to a usergroup by selecting the group from the DropDownList.
<asp:ListView ID="NewUsers" runat="server" DataSourceID="NewUsersSDS" DataKeyNames="ID">
<LayoutTemplate>
<asp:Table ID="groupPlaceholder" runat="server"><asp:TableRow></asp:TableRow></asp:Table>
</LayoutTemplate>
<GroupTemplate>
<asp:TableCell ID="itemPlaceholder" runat="server"></asp:TableCell>
</GroupTemplate>
<ItemTemplate>
<asp:Table ID="NewUsersTable" runat="server" Width="32%" CssClass="inlineTable">
<asp:TableRow>
<asp:TableCell Width="100px"><%# Eval("FullName").ToString.Trim()%></asp:TableCell>
<asp:TableCell>
<asp:HiddenField ID="RowIndex" runat="server" Value="<%# Container.DisplayIndex %>" />
<asp:DropDownList ID="UserGroupSelect" runat="server" DataSourceID="UserGroupSelectSDS" DataValueField="ID" DataTextField="UserGroup"
OnSelectedIndexChanged="UserGroupSelect_SelectedIndexChanged" AutoPostBack="True">
</asp:DropDownList>
</asp:TableCell>
</asp:TableRow>
</asp:Table>
</ItemTemplate>
</asp:ListView>
I've been having issues accessing controls inside of __View controls. I read in a few places that you could access them by NewUsers.FindControl([ControlID as String]) but this doesn't seem to be working for me. I guess this is what's called a dynamic control? Not really sure, feeling a bit lost.
As always, your help is greatly appreciated. ;)
Additional Info / Code
'Now working code, thanks to James :)
Protected Sub ItemBind(ByVal sender As Object, ByVal e As ListViewItemEventArgs) Handles NewUsers.ItemDataBound
Dim lv As ListView = DirectCast(sender, ListView)
If e.Item.ItemType = ListViewItemType.DataItem Then
lv.DataKeys(e.Item.DataItemIndex).Value.ToString() 'get the datakey
End If
End Sub
Protected Sub UserGroupSelect_SelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs)
Dim RowIndex As Integer = CInt(DirectCast(DirectCast(sender, DropDownList).Parent.FindControl("RowIndex"), HiddenField).Value)
Dim pk As Integer = CInt(NewUsers.DataKeys(RowIndex)("ID"))
Try
MessageBox("Update key " + pk.ToString, "Update Key") 'Custom js "alert" box function
Catch ex As Exception
MessageBox("Something went wrong, is the update key empty?")
End Try
End Sub

To access controls in a ListView (or any databound control), you need to use FindControl on the item/row:
ListViewItem item = ListView1.Items[0];
if (item != null)
{
DropDownList ddl = item.FindControl("DropDownList1") as DropDownList;
if (ddl != null)
{
string value = ddl.SelectedValue;
}
}
As for attaching a SelectedIndexChanged event, you can do it like this:
<ItemTemplate>
<asp:DropDownList ID="DropDownList1" runat="server"
AutoPostBack="true"
OnSelectedIndexChanged="DropDownList1_SelectedIndexChanged">
</asp:DropDownList>
<asp:HiddenField ID="HiddenField1" runat="server" Value='<%# Container.DisplayIndex %>' />
</ItemTemplate>
Code-behind:
protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{
int rowIndex = Convert.ToInt32(((HiddenField)((DropDownList)sender).Parent.FindControl("HiddenField1")).Value);
ListViewItem item = ListView1.Items[rowIndex];
if (item != null)
{
//your logic here
}
}
To retrieve a datakey:
protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{
int rowIndex = Convert.ToInt32(((HiddenField)((DropDownList)sender).Parent.FindControl("HiddenField1")).Value);
int pk = (int)ListView1.DataKeys[rowIndex]["PrimaryKey"];
}

Related

I can't access the ID nested inside the ListView <itemtemplate>

I am trying to grab the value of the checkbox every time a user checks it using the following markup:
<!---- <asp:CheckBoxList ID="CheckboxWattage" runat="server" RepeatColumns="1" CellSpacing="-1" RepeatDirection="Vertical" RepeatLayout="Flow" TextAlign="Right" Width="300px">
<asp:ListItem text="" value=""></asp:ListItem>
</asp:CheckBoxList>--->
<asp:Listview id="filterListView" runat="server" DataSourceID="" onitemdatabound="filterListView_ItemDataBound" >
<ItemTemplate>
<asp:CheckBox ID="CheckBox1" value='<%#DataBinder.Eval(Container.DataItem,"UDF_WATTAGE") %>' runat="server"/>
<asp:label ID="LabelValue" AssociatedControlID="CheckBox1" runat="server" text='<%#Eval("UDF_WATTAGE") %>' ></asp:label>
<asp:label Style="font-size:12px; font-style: italic;" ID="countLabel" runat="server" text='<%# "(" + DataBinder.Eval(Container.DataItem,"CountofUDF_WATTAGE") +")" %>' ></asp:label>
</br>
</ItemTemplate>
</asp:Listview>
<asp:Button id="wattagebtn" text="Apply" class="btn btn-danger" style="float:right;" onclick="wattageApply_Click" runat="server"></asp:Button>
<asp:Label ID="Label1" runat="server" Text="hi"></asp:Label>
</div>
</div>
code behind update! I think I was able to grab the CheckBox1 ID. how can I grab the checkbox value? When checked?
I will update once I find the solution for anyone that's having the same issue.
UPDATEEE FOUND THE SOLUTION. i had to put if(!IsPostBack){ }
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
dapter.Fill(ds);
filterListView.DataSource = ds;
filterListView.DataBind();
}
protected void filterListView_ItemDataBound(object sender, ListViewItemEventArgs e)
{
if (e.Item.ItemType == ListViewItemType.DataItem)
{
}
}
protected void wattageApply_Click(Object sender, System.EventArgs e)
{
foreach (ListViewItem item in filterListView.Items)
{
CheckBox cb = item.FindControl("CheckBox1") as CheckBox;
if (cb.Checked == true)
{
string ch;
Label1.Text = cb.Text;
}
else
{
Label2.Text = cb.Text;
}
}
<asp:ListView ID="ListView1" runat="server" DataSourceID="">
<ItemTemplate>
<div>
<asp:CheckBox ID="CheckBox1" runat="server"
OnCheckedChanged="ListViewItemCheckChanged"
Text='<%#DataBinder.Eval(Container.DataItem,"UDF_WATTAGE") %>' />
.
.
.
</div>
</ItemTemplate>
</asp:ListView>
Code Behind (VB.NET):
Protected Sub ListViewItemCheckChanged(sender As Object, e As EventArgs)
Dim cb As CheckBox = sender
// at this point the variable cb contains the user selected checkbox
End Sub
This will allow you to examine the last Checkbox the user clicked
Keep in mind there will be a postback on each click.
This will give you what you are asking for but is probably not the best interface experience for the user.
Typically when presented with multiple check boxes you allow all the user selections and then process the selections with one postback via some submit style button. This would require:
Looping through the ListView's Item Collection,
For each ListViewDataItem find each CheckBox via FindControl("CheckBox1")
Check for CheckBox1.Checked() and act accordingly
Addendum: How to Loop through ListView Items (VB.NET):
Private Sub Button1_Click(sender As Object, e As System.EventArgs) Handles Button1.Click
Dim cb As CheckBox
For Each lvi As ListViewDataItem In ListView1.Items
cb = lvi.FindControl("CheckBox1")
If cb.Checked Then
...
Else
...
End If
Next
End Sub
Addendum: A word about Checkboxes:
An ASP CheckBox doesn't have a value per se. It's "value" is the Boolean "cb.Checked". But there are two ways you can associate a value with CheckBox
1) If the value is not a security issue and not particulary lengthy you can add an Attribute in the ListView ItemDataBound event
Private Sub ListView1_ItemDataBound(sender As Object, e As ListViewItemEventArgs) Handles ListView1.ItemDataBound
If e.Item.ItemType = ListViewItemType.DataItem Then
Dim drv As DataRowView = e.Item.DataItem
Dim cb As CheckBox = e.Item.FindControl("CheckBox1")
cb.Attributes("some-legal-html-attribute-name") = drv("Some_dataset_field")
End If
End Sub
You are doing something similar with this in your aspx:
<asp:CheckBox ID="CheckBox1" runat="server"
value='<%#DataBinder.Eval(Container.DataItem,"UDF_WATTAGE") %>'/>
the above should render to something like this:
<input id="ListviewMangledprefix_CheckBox1" type="checkbox"
value="[value of UDF_WATTAGE FIELD]" />
Inspect the field in the rendered browser page and see if the "value" attribute is being rendered. If so you should be able to access it in the code behind as:
Dim wattage as String = cb.Attributes("value")
2) Better and more secure would be to implement and use ListView1.DataKeys. But this is a much more extensive topic that you should research when you have time

dropdownlist in gridview row data bound is not executing properly

I have a dropdownlist in my gridview. The datas in dropdownlist are "Y" and "N".These two letters. If I select Y then the cell value 6 will be need to become zero. But its not working. Here is my code.
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
DropDownList DropDownList3=(DropDownList)e.Row.FindControl("DropDownList");
//if (DropDownList3 == null)
//if (DropDownList3.SelectedValue == "Y")
if(DropDownList3.SelectedItem.Text == "Y")
{
e.Row.Cells[6].Text = "0";
}
else
{
e.Row.Cells[6].Text = "1";
}
}
}
This is my dropdowlist template field
<asp:TemplateField HeaderText="Alt">
<EditItemTemplate>
<asp:DropDownList ID="DropDownList3" runat="server" >
<asp:ListItem>Y</asp:ListItem>
<asp:ListItem>N</asp:ListItem>
</asp:DropDownList>
</EditItemTemplate>
<FooterTemplate>
<asp:DropDownList ID="DropDownList3" runat="server" >
<asp:ListItem>Y</asp:ListItem>
<asp:ListItem>N</asp:ListItem>
</asp:DropDownList>
</FooterTemplate>
<ItemTemplate>
<asp:DropDownList ID="DropDownList3" runat="server" >
<asp:ListItem>Y</asp:ListItem>
<asp:ListItem>N</asp:ListItem>
</asp:DropDownList>
</ItemTemplate>
</asp:TemplateField>
First, You have to set AutoPostBack="true" for DropDownList3, and You have to create EventHandler for ddl, but in RowCreated not in RowDataBound.
There is example (it's vb.net) :
aspx:
<asp:TemplateField HeaderText="Alt">
<ItemTemplate>
<asp:DropDownList ID="DropDownList3" runat="server" AutoPostBack="true">
<asp:ListItem>Y</asp:ListItem>
<asp:ListItem>N</asp:ListItem>
</asp:DropDownList>
</ItemTemplate>
</asp:TemplateField>
and then, code behind :
Private Sub GridView1_RowCreated(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles grid1.RowCreated
If e.Row.RowType = DataControlRowType.DataRow Then
Dim ddl As DropDownList = CType(e.Row.FindControl("DropDownList3"), DropDownList)
AddHandler ddl.SelectedIndexChanged, AddressOf ddlChange
End If
End Sub
Private Sub ddlChange(ByVal sender As Object, ByVal e As EventArgs)
Dim ddl As DropDownList = DirectCast(sender, DropDownList)
Dim row As GridViewRow = ddl.NamingContainer
If ddl.SelectedItem.Text = "Y" Then
row.Cells(6).Text = "0"
Else
' do what You want
End If
End Sub
It's very important You don't bind Your GridView after every PostBack, and, of course, EnableViewState must be set to True.
Since I'm working in vb.net, I'll try to convert this code into c#.
Update :
There is c# code (I used online converter) :
private void GridView1_RowCreated(object sender, System.Web.UI.WebControls.GridViewRowEventArgs e) {
if ((e.Row.RowType == DataControlRowType.DataRow)) {
DropDownList ddl = ((DropDownList)(e.Row.FindControl("DropDownList3")));
ddl.SelectedIndexChanged += new System.EventHandler(this.ddlChange);
}
}
private void ddlChange(object sender, EventArgs e) {
DropDownList ddl = ((DropDownList)(sender));
GridViewRow row = ddl.NamingContainer;
if ((ddl.SelectedItem.Text == "Y")) {
row.Cells[6].Text = "0";
} else {
// do what You want
}
}

How do I set dropdownlist selectedvalue in edit mode but not in gridview?

With the code below, when I click the Edit button, the selectvalue in gridview dropdownlist is retained while at the same time, retaining the rest of the dropdownlist values so user can select a different value.
Protected Sub RowDataBound(ByVal sender As Object, ByVal e As GridViewRowEventArgs)
If e.Row.RowType = DataControlRowType.DataRow AndAlso gvCustomers.EditIndex = e.Row.RowIndex Then
Dim ddlRoles As DropDownList = DirectCast(e.Row.FindControl("ddlRoles"), DropDownList)
Dim query As String = "select RoleId, Roles from ROLES"
Dim cmd As New SqlCommand(query)
ddlRoles.DataSource = GetData(cmd)
ddlRoles.DataTextField = "Roles"
ddlRoles.DataValueField = "RoleId"
ddlRoles.DataBind()
ddlRoles.Items.FindByValue(TryCast(e.Row.FindControl("lblUserRole"), Label).Text).Selected = True
End If
End Sub
'//Markup:
<asp:Label ID="lblUserRole" runat="server" Text='<%# Eval("RoleId")%>' Visible = "false"></asp:Label>
<asp:DropDownList ID = "ddlRoles" runat = "server">
</asp:DropDownList>
These work fine for gridview.
However, I would like to change the codebehind to regular web form so I can manipulate the layout out better.
In other words, I have the layout like this:
First Name: _____________
Last Name: ______________
Roles: ________________
My understanding is that in gridview, layout is vertical and is not flexible.
We would like our layout to be horizontal.
Thank you in advance for your assistance
You have to use TemplateField and within that template you can specify your layout, which could contain multiple fields, and use different controls for Edit/Insert operations, like in the following sample:
Listing 1.
<asp:TemplateField HeaderText="Toll-Free: Area/Phone #">
<ItemTemplate>
(
<%# DataBinder.Eval( Container.DataItem, "A_TollFree_AreaCode" )%>
)
<%# DataBinder.Eval(Container.DataItem, "A_TollFree_Number")%>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="txtAreaCode" runat="server"
CssClass="phoneAreaCode" MaxLength="3"
Text='<%# Bind("A_TollFree_AreaCode") %>' />
<asp:TextBox ID="txtPhoneNumber" runat="server"
CssClass="phoneNumber" MaxLength="20"
Text='<%# Bind("A_TollFree_Number") %>' />
</EditItemTemplate>
<InsertItemTemplate>
<asp:TextBox ID="txtAreaCode" runat="server"
CssClass="phoneAreaCode" MaxLength="3"
Text='<%# Bind("A_TollFree_AreaCode") %>' />
<asp:TextBox ID="txtPhoneNumber" runat="server"
CssClass="phoneNumber" MaxLength="20"
Text='<%# Bind("A_TollFree_Number") %>' />
</EditItemTemplate>
</InsertItemTemplate>
</asp:TemplateField>
Regarding you second question (in comments), please refer to the Listing 2. that demonstrates the general technique of accessing various Controls in GridView:
Listing 2.
protected void GridView1_OnRowDataBound(object sender, GridViewRowEventArgs e)
{
try
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
string _strPhone = DataBinder.Eval(e.Row.DataItem, "txtPhoneNumber").ToString();
Button btn = (Button)e.Row.Cells[0].Controls[1];
}
}
catch { }
}
Best Regards,

Gridview template radiobuttonlist SelectedInxedChanged, Getting the row the list was in when it fired

I have a Gridview in which one of the template fields has a radiobuttonlist and a dropdownlist. How can I access the row that the radiobuttonlist is in on the SelectedIndexChanged event, so I don't end up updating all of the dropdownlist inside the that template field of the gridview. I don't have any code currently but any help would be greatly appreciated
<asp:TemplateField HeaderText="Column with ListControls" >
<ItemTemplate>
<asp:DropDownList ID="DropdownList1" OnSelectedIndexChanged="SomethingChanged" AutoPostBack="true" runat="server" >
<asp:ListItem Text="1"></asp:ListItem>
<asp:ListItem Text="2"></asp:ListItem>
</asp:DropDownList>
<asp:RadioButtonList ID="RadioButtonList1" OnSelectedIndexChanged="SomethingChanged" AutoPostBack="true" runat="server">
<asp:ListItem Text="1"></asp:ListItem>
<asp:ListItem Text="2"></asp:ListItem>
</asp:RadioButtonList>
</ItemTemplate>
</asp:TemplateField>
Codebehind VB.NET:
Protected Sub SomethingChanged(ByVal sender As Object, ByVal e As EventArgs)
'in this example this handler is used for both, Dropdownlist and RadiobuttonList'
Dim listControl = DirectCast(sender, ListControl)
Dim row = DirectCast(listControl.NamingContainer, GridViewRow)
Dim item = listControl.SelectedItem
'with FindControl on the row you could also find controls in other columns...'
End Sub
C#:
protected void SomethingChanged(object sender, EventArgs e)
{
//in this example this handler is used for both, Dropdownlist and RadiobuttonList
var listControl = (ListControl)sender;
var row = (GridViewRow)listControl.NamingContainer;
var item = listControl.SelectedItem;
//with FindControl on the row you could also find controls in other columns...
}

fetching values from the repeater control in ItemDataBound event

how to fetch values of repeater control in the ItemDataBound event
i wrote the following asp code
<asp:Repeater ID="repeaterItems" runat="server" OnItemDataBound="rptData_ItemDataBound" >
<itemtemplate>
<tr>
<td style="font-family:Tahoma; font-size:small"><asp:Label id="content" runat="server"> <%#DataBinder.Eval(Container.DataItem, "cont")%></asp:Label></td>
</tr>
<tr><td style="font-family:Verdana; font-size:small"><asp:Label id="url" runat="server"><a style="color:Green" href="<%#DataBinder.Eval(Container.DataItem, "url")%>" target="_blank"><%#DataBinder.Eval(Container.DataItem, "url")%></a></asp:Label></td></tr>
<tr><td><asp:LinkButton runat="server" ID="glossary" >Glossary</asp:LinkButton></td></tr>
<tr><td><asp:HiddenField runat="server" ID="id1"/><%#DataBinder.Eval(Container.DataItem, "id")%></td></tr>
<tr><td></td></tr><tr><td></td></tr><tr><td></td></tr>
</itemtemplate>
</asp:Repeater>
and the ItemDataBound event in vb.net
Protected Sub rptData_ItemDataBound(ByVal source As Object, ByVal e As RepeaterItemEventArgs)
Dim content As String = ""
Dim url As String = ""
Dim lbl1 As Label = TryCast(e.Item.FindControl("content"), Label)
Dim lbl2 As Label = TryCast(e.Item.FindControl("url"), Label)
content = lbl1.Text
url = lbl2.Text
Dim btn As LinkButton = CType(e.Item.FindControl("glossary"), LinkButton)
btn.PostBackUrl = "glossary.aspx?cont=" + content + "&url=" + url
end sub
but i get empty value in content and url...
please help
First of all in markup use Text property of label, do not put databinder.Eval in
<asp:Label ..> do not put content here </asp:Label>
In item databound event first find out control in which template.
follow this example :
Markup:
<asp:Repeater ID="Repeater1" runat="server"
onitemdatabound="Repeater1_ItemDataBound">
<HeaderTemplate>
</HeaderTemplate>
<ItemTemplate>
<asp:Label ID="Label1" runat="server" Text='<%# Eval("content") %>'></asp:Label>
<asp:LinkButton ID="LinkButton1" runat="server">LinkButton</asp:LinkButton>
</ItemTemplate>
<AlternatingItemTemplate></AlternatingItemTemplate>
<SeparatorTemplate></SeparatorTemplate>
</asp:Repeater>
Source Code :
C#:
protected void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item)
{
Label lbl = (Label)e.Item.FindControl("Label1");
LinkButton link = (LinkButton)e.Item.FindControl("LinkButton1");
link.PostBackUrl = "abcd/" + lbl.Text;
}
}
VB.Net:
Protected Sub Repeater1_ItemDataBound(sender As Object, e As RepeaterItemEventArgs)
If e.Item.ItemType = ListItemType.Item Then
Dim lbl As Label = DirectCast(e.Item.FindControl("Label1"), Label)
Dim link As LinkButton = DirectCast(e.Item.FindControl("LinkButton1"), LinkButton)
link.PostBackUrl = "abcd/" + lbl.Text
End If
End Sub

Resources