Accessing Controls on ListView Edit Command - asp.net

In my ListView I have an ItemTemplate and EditItemTemplate which look something like this, respectively.
------->
When I click the "Edit" button, and it switches to the EditItemTemplate view on the right, I want to prefill the Textbox and select the corresponding option in the DropDownList. How can I do this?
Before you say to use something like the following, please know that I've already explored every possible variation I can think of. Sorry to be so demanding, but please be prepared to walk me through this one if you answer. ^.^ I've been stuck on this issue for literally months :(
Dim lv As ListView = DirectCast(sender, ListView) 'sender is the ListView on the ItemCommand event
Dim ddl As DropDownList = DirectCast(lv.Items(0).FindControl("NewProductName_ddl"), DropDownList)
Dim tb As TextBox = DirectCast(lv.Items(0).FindControl("NewProductName_tb"), TextBox)
UPDATE - RAWR!!
Oh my freaking goodness, SO CLOSE, but no cigar. The following code worked for prefilling when only one item was in the ListView, but when more than one items exist, it throws a NullReferenceException :(
'PROBLEM WAS HERE: Compare to the working code in my answer.
Protected Sub NewProduct_ItemDataBound(ByVal sender As ListView, ByVal e As ListViewItemEventArgs) Handles NewProduct.ItemDataBound
If sender.EditIndex > -1 Then
Dim ddl As DropDownList = DirectCast(e.Item.FindControl("NewProductName_ddl"), DropDownList)
Dim tb As TextBox = DirectCast(e.Item.FindControl("NewProductName_cb"), TextBox)
ddl.Items.FindByValue(sender.DataKeys(sender.EditIndex)("ID").ToString).Selected = True 'Prefills the DropDownList
tb.Text = sender.DataKeys(sender.EditIndex)("Product").ToString 'Prefills the TextBox
End If
End Sub

EUREKA!!
I am elated beyond imagination!! All caps, nor bold do justice to how happy I am right now :)
First I wanna give props to this question which got me pointed in the right direction. Now onto the answer, which is the most ideal variation I have found of the answer provided in the above link:
The ItemDataBound event is the key, but it's important to note that this event will fire for each item that exists in your ListView and for that reason, you must be careful in your approach. Here are two options that worked equally well for me.
Option 1 - Most elegant; only runs FindControl on the item in question rather than all items.
Protected Sub NewProduct_ItemDataBound(ByVal sender As ListView, ByVal e As ListViewItemEventArgs) Handles NewProduct.ItemDataBound
Dim i As Integer = sender.EditIndex
If i = e.Item.DataItemIndex Then
Dim ddl As DropDownList = DirectCast(e.Item.FindControl("NewProductName_ddl"), DropDownList)
Dim tb As TextBox = DirectCast(e.Item.FindControl("NewProductName_cb"), TextBox)
ddl.Items.FindByValue(sender.DataKeys(i)("ID").ToString).Selected = True 'Prefills the DropDownList
tb.Text = sender.DataKeys(i)("Product").ToString 'Prefills the TextBox
End If
End Sub
Option 2 - Based on the referenced question, but with a crucial check to ensure non-null object.
Protected Sub NewProduct_ItemDataBound(ByVal sender As ListView, ByVal e As ListViewItemEventArgs) Handles NewProduct.ItemDataBound
Dim i As Integer = sender.EditIndex
If i > -1 Then
Dim ddl As DropDownList = DirectCast(e.Item.FindControl("NewProductName_ddl"), DropDownList)
Dim tb As TextBox = DirectCast(e.Item.FindControl("NewProductName_cb"), TextBox)
If Not IsNothing(ddl) Then
ddl.Items.FindByValue(sender.DataKeys(i)("ID").ToString).Selected = True 'Prefills the DropDownList
End If
If Not IsNothing(tb) Then
tb.Text = sender.DataKeys(i)("Product").ToString 'Prefills the TextBox
End If
End If
End Sub
I may make improvements to this answer later, but this did the trick for me. :)

Great post! I had the same problem and you saved me hours of trial and error. Just wanted to point out that when using your first option with .NET Framework 3.5 or lower, DataItemIndex isn't available. To work around it you can replace
If i = e.Item.DataItemIndex Then
With
If i = DirectCast(e.Item, IDataItemContainer).DataItemIndex Then

Related

Access the value of dropdownlist in gridview edit mode, in DropDownList_SelectedIndexChanged event

I am trying to perfrom a postback with a Dropdownlist in a Gridview in Edit Mode. I am having problems getting to the value of the drop down. I can not do this in the RowDatabound event.
Postback is not over writing the row, I am stepping into the DropDownList7_SelectedIndexChanged event where I want to perform some operations, so it hasn't even gotten there. I do have the If Postback in the page load event.
Protected Sub DropDownList7_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs)
Dim row As GridViewRow = DirectCast(GridView1.Rows.Item(0), GridViewRow)
Dim newNumDDL As DropDownList = row.Cells(0).FindControl("DropDownList7")
Dim newVal As Integer = newNumDDL.SelectedValue
Dim newKey As String = newNumDDL.SelectedItem.ToString
Dim newindex As Integer = newNumDDL.SelectedIndex
Issue I believe is with the findcontrol I can not find the DDL, keeps coming back nothing.
Thanks for any help.
Can you not use:
Dim newNumDDL As DropDownList = DirectCast(sender, DropDownList)

Filling the dropdown from sql bug

Good afternoon people have been trying to fill a dropdown using a sql command, until so good, when I click on the dropdown it shows all the items, but when I try to click on an item in the dropdown it always returns the first item in the dropdown .... follows the codes, what i want to do is get the selected value and item from the dropdown and save it on a label for future use.
I appreciate all the support possible,
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
utilizador.Text = Me.Context.User.Identity.Name
If (Not Page.IsPostBack) Then
escolhePerfil()
End If
'DropDownPerfil.DataBind()
lbperfil2.Text = DropDownPerfil.SelectedItem.Text
lbnome.Text = DropDownPerfil.SelectedValue
End Sub
Function escolhePerfil() As Boolean
Dim connstring As String = "Data Source=10.2.24.17;Persist Security Info=True;User ID=sa;Password=Pr0dUn1C0$qL;database=ePrimavera"
Dim SQLData As New System.Data.SqlClient.SqlConnection(connstring)
Dim cmdSelect As New System.Data.SqlClient.SqlCommand("SELECT u.WindowsUser,u.Email ,g.Description, u.Login FROM [ePrimavera].[dbo].[PLT_Users] as u,[ePrimavera].[dbo].[PLT_UserGroups] as ug, [ePrimavera].[dbo].[PLT_Groups] as g where u.ID = ug.UserID And ug.GroupID = g.ID and u.WindowsUser like 'bancounico\" & utilizador.Text & "'", SQLData)
SQLData.Open()
Dim dtrReader As System.Data.SqlClient.SqlDataReader = cmdSelect.ExecuteReader()
If dtrReader.HasRows Then
DropDownPerfil.DataValueField = "Login"
DropDownPerfil.DataTextField = "Description"
DropDownPerfil.DataSource = dtrReader
DropDownPerfil.DataBind()
End If
SQLData.Close()
Return True
End Function
.aspx
<asp:DropDownList ID="DropDownPerfil" runat="server"
Height="16px" Width="202px" CssClass="DropBorderColor">
</asp:DropDownList>
try the following code:
Protected Sub DropDownPerfil_SelectedIndexChanged(sender As Object, e As EventArgs)
lbperfil2.Text = DropDownPerfil.SelectedItem.Text
lbnome.Text = DropDownPerfil.SelectedValue
End Sub
The problem is that you are trying to get the value "too early". The value is not valid in the Page_Load, since the control's OnLoad event fired after the Page's OnLoad (Page_Load) event.
The way, what the others wrote the correct, since the Event handlig section (inclueding control's onchanged event) will process after the Load section.
For more details check the offical ASP.NET life cycle site in the MSDN
The likely reason is that some (if not all) the values you are assigning to the DropDownList for Login are occur more than once.
When you then select an item in the DDL, if the value of that item occurs more than once, the selected index will highlight the first instance. To test this, comment out DropDownPerfil.DataValueField = "Login"
I am sure upon selection, it will highlight the correct item you intended on selecting.

Creating buttons dynamically in ListView

I have a following problem. I have a ListView which returns data from SQL table. One of its columns looks like "Ambient/Trance/Goa Trance/House".
All i want to do is parse this column and create buttons for each value, for example a button for "Ambient", a button for "Trance", etc.
I tried to create buttons in ItemDataBound event in the following way:
Dim ListView_Albums_PlaceHolder_Artists As PlaceHolder = e.Item.FindControl("ListView_Albums_PlaceHolder_Artists")
Dim Artists As String() = e.Item.DataItem("album_artists").ToString.Split("/")
Dim ArtistsN As String() = e.Item.DataItem("album_artists_n").ToString.Split("/")
Dim ListView_Albums_Literal_Artists As New Literal
If Artists.Length = 1 Then
ListView_Albums_Literal_Artists.Text = "Artist: "
Else
ListView_Albums_Literal_Artists.Text = "Artists: "
End If
ListView_Albums_PlaceHolder_Artists.Controls.Add(ListView_Albums_Literal_Artists)
For Integer1 As Integer = 0 To Artists.Length - 1
Dim ListView_Albums_LinkButton_Artist As New LinkButton
ListView_Albums_LinkButton_Artist.Text = ArtistsN(Integer1)
ListView_Albums_LinkButton_Artist.CommandName = "Artist"
ListView_Albums_LinkButton_Artist.CommandArgument = Artists(Integer1)
ListView_Albums_LinkButton_Artist.CssClass = "a-03"
ListView_Albums_PlaceHolder_Artists.Controls.Add(ListView_Albums_LinkButton_Artist)
Dim ListView_Albums_Literal As New Literal
ListView_Albums_Literal.Text = ", "
If Not Integer1 = Artists.Length - 1 Then
ListView_Albums_PlaceHolder_Artists.Controls.Add(ListView_Albums_Literal)
End If
Next
They created fine but they didn't work at all. I tried to Add Handler for Click or Command event but it also didn't help.
Please help me to solve my problem!
Edit:
As VinayC suggested I changed ItemDataBound to ItemCreated. That helped, but I faced another problem: as far as I understand e.Item.DataItem or, maybe, e.Item becomes Nothing on PostBacks so the buttons do not work.
How to solve that problem? Thanks once again!
I believe that buttons must be getting created late in page life cycle and hence not responding to events.
You may want to try moving your code in ItemCreated event and use ListView's ItemCommand event to trap these. Yet another suggestion is to assign (different) ID to your link buttons - for example
ListView_Albums_LinkButton_Artist.ID = "A" & Artists(Integer1)
In case, you want to attach an click event handler directly to buttons then ID is must.
So, I solved my problem. The solution wasn't simple but here it is:
In ItemCreated event I firstly count the number of buttons, then save it to ViewState, and only then I create buttons. I had to save the number of buttons to ViewState because on every postback e.Item.DataItem becomes Nothing.
Maybe there is a simplier solution but I found only that one...
Sub OnItemCreated(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.ListViewItemEventArgs)
Dim ListView_Albums_PlaceHolder_Artists As PlaceHolder = e.Item.FindControl("ListView_Albums_PlaceHolder_Artists")
If Not ListView_Albums_PlaceHolder_Artists Is Nothing Then
If Not e.Item.DataItem Is Nothing Then
ViewState("Length") = e.Item.DataItem("album_artists").ToString.Split("/").Length
End If
If Not ViewState("Length") Is Nothing Then
Dim Length As Integer = ViewState("Length")
For Integer1 As Integer = 0 To Length - 1
Dim ListView_Albums_LinkButton_Artist As New LinkButton
ListView_Albums_LinkButton_Artist.ID = "ListView_Albums_LinkButton_Artist_" & Integer1
ListView_Albums_PlaceHolder_Artists.Controls.Add(ListView_Albums_LinkButton_Artist)
Next
End If
End If
End Sub
Sub OnItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.ListViewItemEventArgs)
Dim ListView_Albums_PlaceHolder_Artists As PlaceHolder = e.Item.FindControl("ListView_Albums_PlaceHolder_Artists")
If Not ListView_Albums_PlaceHolder_Artists Is Nothing Then
If Not e.Item.DataItem Is Nothing Then
Dim Artists As String() = e.Item.DataItem("album_artists").ToString.Split("/")
Dim Artists_N As String() = e.Item.DataItem("album_artists_n").ToString.Split("/")
For Integer1 As Integer = 0 To Artists.Length - 1
Dim ListView_Albums_LinkButton_Artist As LinkButton = e.Item.FindControl("ListView_Albums_LinkButton_Artist_" & Integer1)
ListView_Albums_LinkButton_Artist.CommandArgument = Artists(Integer1)
ListView_Albums_LinkButton_Artist.Text = Artists_N(Integer1)
ListView_Albums_LinkButton_Artist.CssClass = "a-03"
Next
End If
End If
End Sub

Implementing pager control for gridview?

Is there a way to select the number of records/rows to display in the gridview by a drop down list ?
If you mean a dynamic change of the number of rows based on a DDL selection, sure it can be done.
I would suggest using an AJAX method on the select action that would query the DB for the exact amount of rows and returning. Far too often I've seen a query bring back thousands of rows and the paging etc is done in memory. Much more efficient to just get the rows/page directly from the DB and preserve bandwidth.
Not sure if that is exactly what you were asking, but hope it helps.
You can also use RowCreated to create your Dropdownlist in Codebehind. Have a look at following example(VB.Net):
Private Sub Yourgrid_RowCreated(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles Yourgrid.RowCreated
Select Case e.Row.RowType
Case DataControlRowType.Pager
Dim ddlPager As New DropDownList
ddlPager.ID = "DdlPager"
ddlPager.AutoPostBack = True
ddlPager.ToolTip = "Change Pagesize"
ddlPager.Items.Add("5")
ddlPager.Items.Add("10")
ddlPager.Items.Add("25")
ddlPager.Items.Add("50")
ddlPager.Items.Add("100")
ddlPager.SelectedValue = "10"
AddHandler ddlPager.SelectedIndexChanged, AddressOf Me.PageSizeChanged
e.Row.Cells(0).ColumnSpan -= 1
Dim td As New TableCell
Dim span1 As New Label
span1.Text = "Show"
span1.Style("margin-left") = "50px"
td.Controls.Add(span1)
td.Controls.Add(ddlPager)
Dim span2 As New Label
span2.Text = "rows per page"
td.Controls.Add(span2)
e.Row.Cells.Add(td)
End Select
End Sub
Private Sub PageSizeChanged(ByVal sender As Object, ByVal e As System.EventArgs)
Dim ddlPager As DropDownList = DirectCast(sender, DropDownList)
Dim newPageSize As Int32 = Int32.Parse(ddlPager.SelectedValue)
YourGrid.PageSize = newPageSize 'change the PageSize of the Grid'
DataBindYourGrid() 'call the function that Binds your grid to the Datasource'
UpdYourgrid.Update() 'if you use Ajax, update the UpdatePanel of this GridView'
End Sub
On this way you autogenerate the Dropdonwlist on every postback and add it to the Gridview's pager. The code is reusable for any GridView.

Accessing TextBox Column in RadGrid By Telerik

Do you know how to access textboxes added to a radgrid that are not bound but are used to trap any row related input a user typed in to the textbox for that column.
I need to access this data server side when a postback occurs.
Your thoughts are greatly appreciated
Thanking you
Tony
That depends on how those textboxes are being added/created. If by 'not bound' you mean they are in Template columns you should be able to use .FindControl in one of the grid's events to grab that textbox.
And again which event will depend on what is causing the postback to happen.
For the purpose of this code example I'll assume you are dealing with a Command item on the grid
Private Sub radGrid_ItemCommand(ByVal source As Object, ByVal e As Telerik.WebControls.GridCommandEventArgs) Handles RadGrid1.ItemCommand
Select Case e.CommandName
Case "Update"
Dim txt as Textbox
txt = e.Item.FindControl("textboxID")
If Not txt is Nothing Then someObject.someString = txt.Text
Case Else
'do something else
End Sub
Hope that helps.
Private Sub radGrid_ItemCommand(ByVal source As Object, ByVal e As Telerik.WebControls.GridCommandEventArgs) Handles RadGrid1.ItemCommand
Select Case e.CommandName
Case "Update"
Dim txt as Textbox
txt = e.Item.FindControl("textboxID")
If Not txt is Nothing Then someObject.someString = txt.Text
Case Else
'do something else
End Sub

Resources