Listview DropDownList FindControl without Edit Button - asp.net

I am having trouble populating a dropdownlist from a dataset when the dropdownlist is embedded in a listview. I get "Object reference not set to an instance of an object." because, I believe, I am not accessing the dropdownlist correctly using FindControl
We do NOT want edit buttons on this listview, we want every line to be editable at once. Most examples online have edit buttons. That might be part of my problem.
Most examples online also use a datasource defined in the ASPX page. We've been using exclusively Oracle.DataAccess sys_refcursor to populate datasets, and then use the dataset as the datasource. So I have to populate the drop down from the VB side, not but using a datasource in the aspx page.
I can independantly populate a listview, and independantly populate a dropdownlist, but walking and chewing gum is a failure.
So here are some snippets of what I got:
<asp:ListView ID="lvMFGRS" runat="server">
<ItemTemplate>
<tr runat="server">
<td runat="server">
<asp:Label ID="NameLabel" runat="server" Text='<%#Eval("NEW_MANUFACTURER")%>' />
</td>
<td runat="server">
<asp:dropdownlist ID="ddMFGRS" runat="server" />
</td>
</tr>
</ItemTemplate>
</asp:ListView>
Then something like this on the vb side:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
newmfglist() 'just sticks data in the "NameLabel" and databinds, and this works fine.
For Each lvItem In lvMFGRS.Items
Dim ddlist As DropDownList = lvMFGRS.FindControl("ddMFGRS")
For Each tbl2 As DataTable In dsmfgrlist.Tables
For Each dr2 As DataRow In tbl2.Rows
Dim str1 As String
Dim str2 As String
str1 = "dog" 'dr2.Field(Of String)("DataValueField")
str2 = "cat" 'dr2.Field(Of String)("DataTextField")
ddlist.Items.Add(New ListItem(str2, str1)) 'this is where I get the error
Next
Next
Next
End Sub
So what do you think I'm doing wrong...

The answer is:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
newmfglist() 'just sticks data in the "NameLabel" and databinds, and this works fine.
For Each lvItem In lvMFGRS.Items
Dim ddlist As DropDownList = lvItem.FindControl("ddMFGRS")
For Each tbl2 As DataTable In dsmfgrlist.Tables
For Each dr2 As DataRow In tbl2.Rows
Dim str1 As String
Dim str2 As String
str1 = "dog" 'dr2.Field(Of String)("DataValueField")
str2 = "cat" 'dr2.Field(Of String)("DataTextField")
ddlist.Items.Add(New ListItem(str2, str1)) 'this is where I get the error
Next
Next
Next

Related

ASP Repeater not showing data

I'm trying to get an alphabet pager working in GridView. It does work, but only one letter shows up in the repeater that I'm using to show the letters. I've read other posts and looked at my code and it seems like it should be working, but it's not.
Any help would be appreciated.
Here is my html
<asp:Repeater ID="rptAlphabets" runat="server">
<ItemTemplate>
<asp:LinkButton ID="lnkBtn1" runat="server" Text='<%#Eval("Value")%>' Visible='<%# Convert.ToBoolean(Eval("Selected"))%>' OnClick="Alphabet_Click"/>
<asp:Label ID="lblAlpha" runat="server" Text='<%#Eval("Value")%>' Visible='<%# Convert.ToBoolean(Eval("Selected"))%>' />
</ItemTemplate>
</asp:Repeater>
Here is my code behind
Private Sub GenerateAlphabets()
Dim alphabets As New List(Of ListItem)()
Dim alphabet As New ListItem
alphabet.Value = "ALL"
alphabet.Selected = alphabet.Value.Equals(ViewState("CurrentAlphabet"))
alphabets.Add(alphabet)
For i As Integer = 65 To 90
alphabet = New ListItem()
alphabet.Value = [Char].ConvertFromUtf32(i)
alphabet.Selected = alphabet.Value.Equals(ViewState("CurrentAlphabet"))
alphabets.Add(alphabet)
Next
rptAlphabets.DataSource = alphabets
rptAlphabets.DataBind()
End Sub
I'm using most of the code from an aspsnippets method.
EDIT :
I'm calling the GenerateAlphabets from my Page_Load
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Try
ClearMessages()
If Not IsPostBack Then
ViewState("CurrentAlphabet") = "ALL"
Me.GenerateAlphabets()
BindGrids()
BindDropDownListBoxes()
End If
Catch ex As Exception
Me.HandleError(ex)
End Try
End Sub
Change your LinkButton code like this.
<asp:LinkButton ID="lnkBtn1" runat="server"
Text='<%#Eval("Value")%>'
Visible='<%# Convert.ToBoolean(Eval("Selected")) = False %>'
OnClick="Alphabet_Click"/>
Reason: You are hiding all LinkButtons that are not currently selected. You should be showing them instead.

Reading data in a listview without a selection

I have a timer running on an Update Panel with a Listview showing a page size of 1. The timer increments the data pager as it cycles through many records.
In the Protected Sub timer_Tick Event I would like to read a few values from the ListView Page. Is there an easy way to do this?
The data is currently binding via a SQLDataSource, but this is temporary while other page development is underway. So I cannot rely on that data set for getting the info needed.
Something like....
val1 = listviewName.SelectedItems(0).SubItems(3).Text
val2 = listviewName.SelectedItems(0).SubItems(4).Text
One issue is that the record will not be selected. The Listview is displaying the data set in an ItemTemplate.
<ItemTemplate>
<tr>
<td>Position C:</td>
<td><asp:Label ID="Label50" runat="server" Text='<%# Eval "Pos_C") %>' />
</td>
</tr>
<tr>
<td>Position D</td>
<td><asp:Label ID="Label51" runat="server" Text='<%# Eval("Pos_D") %>' />
</td>
</tr>
</ItemTemplate>
Abbreviated layout of itemtemplate.
For anyone interested, I solved the above question with the code below....
Protected Sub ListView1_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.ListViewItemEventArgs) Handles ListView1.ItemDataBound
'Get the item object.
Dim dataItem As ListViewDataItem = CType(e.Item, ListViewDataItem)
Dim item As ListViewItem = e.Item
' Get the Label control in the item.
Dim myVal1Lbl As Label = CType(item.FindControl("Label50"), Label)
Dim myVal2Lbl As Label = CType(item.FindControl("Label51"), Label)
Dim myVal1 As String = myVal1Lbl.Text
Dim myVal2 As String = myVal2Lbl.Text
End Sub
Works great.

ASP.NET - Accessing a Repeater nested in a GridView column?

I have a blank Repeater nested inside a column in a GridView and want to use a button in the GridView to populate the Repeater on demand via code behind. I am having difficulties referencing the repeater inside my button's onCommand sub.
Here is the relevant markup:
<asp:GridView ID="Submission" runat="server" AllowPaging="true" AllowSorting="true" />
<Columns>
..........
<asp:TemplateField HeaderText="Action">
<ItemTemplate>
<asp:ImageButton ID="AdminEditSubmission" runat="server" ImageUrl="edit_15.png"
alt="" OnCommand="loadDetails" CommandArgument="X" />
</ItemTemplate>
</asp:TemplateField>
..........
<asp:TemplateField>
<ItemTemplate>
<asp:Repeater ID="RptSubmissionDetail" runat="server">
</asp:Repeater>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
For the sake of this small example, I will simply try to update the repeater's header with "Hello world". However, when it gets to the last line, I get the dreaded "Object reference not set to an instance of an object" error.
Sub loadDetails(sender As Object, e As CommandEventArgs)
Dim rpt As Repeater = CType(Page.FindControl("RptsSubmissionDetail"), Repeater)
Dim tmpHdr As TemplateBuilder = New TemplateBuilder
tmpHdr.AppendLiteralString("Hello World")
rpt.HeaderTemplate = tmpHdr
End Sub
Can anyone tell me how to reference this repeater from my ImageButton click sub? I have tried several, with Page.FindControl("RptsSubmissionDetail") only being my latest attempt.
In GridView's RowCommand you need to use FindControl on the GridViewRow:
Sub Submission_RowCommand(ByVal sender As Object, ByVal e As GridViewCommandEventArgs)
If e.CommandName = "loadDetails" Then
' Convert the row index stored in the CommandArgument
' property to an Integer.
Dim index = Convert.ToInt32(e.CommandArgument)
' Retrieve the row that contains the button clicked
' by the user from the Rows collection.
Dim row = Submission.Rows(index)
Dim repeater = DirectCast(row.FindControl("RptSubmissionDetail"), Repeater)
End If
End Sub
From the ImageButton's click event it's nearly the same. Cast the sender argument to the ImageButton and it's NamingContainer property to the GridViewRow. Then use FindControl as shown above:
Sub ImageButton_Click(ByVal sender As Object, ByVal e As EventArgs)
Dim img = DirectCast(sender, ImageButton)
Dim row = DirectCast(img.NamingContainer, GridViewRow)
Dim repeater = DirectCast(row.FindControl("RptSubmissionDetail"), Repeater)
End Sub
In your ImageButton Click event write the following code
For Each row As GridViewRow In Submission.Rows
Dim r As Repeater = DirectCast(row.FindControl("RptsSubmissionDetail"), Repeater)
If r IsNot Nothing Then
' do your work
End If
Next
or if you want to find repearter in a particular row you can find it as
Dim r As Repeater = DirectCast(Submission.Rows[0].FindControl("RptsSubmissionDetail"), Repeater) ' Give the right index
If r IsNot Nothing Then
' do your work
End If

how to get value of dropdownlist which is inside a gridview on the click of a button?

I have a dropdownlist inside the gridview. Now i want when i click on a button then i can check the value of dropdownlist. I have fired rowcommand event of gridview for it but debugger is not able to go reach there..Please help me..My Code is
Protected Sub grd_Test_RowCommand(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewCommandEventArgs) Handles grd_Test.RowCommand
If e.CommandName = "Select" Then
End If
End Sub
my Source code is
<asp:GridView ID="grd_UnAssignProperties" runat="server" AutoGenerateColumns="False"><Columns>
<asp:TemplateField HeaderText="Assign To">
<ItemTemplate>
<asp:DropDownList ID="drp_UnAssignProp" runat="server">
<asp:ListItem Value="" >Default</asp:ListItem>
</asp:DropDownList>
</ItemTemplate>
</asp:TemplateField>
</Columns></asp:GridView><tr><td><asp:Button ID="btn_Save" runat="server" CommandName="Select" Text="Submit" />
try this
DropDownList ddl = (DropDownList)GridView1.Rows[e.RowIndex].Cells[0].FindControl("drp_UnAssignProp");
string val = ddl.SelectedValue;
try
string val = (DropDownList)GridView1.Rows[e.RowIndex].Cells[0]
.FindControl("drp_UnAssignProp").SelectedValue;
First of all, since the button btn_Save isn't inside the GridView, clicking on it won't raise the grd_Test_RowCommand, either move the button inside GridView or you have to raise it manually like this:
Copied from asp.net forum:
Protected Sub Button1_Click(sender As Object, e As EventArgs)
Dim commandArgs As New CommandEventArgs("Command Name Here", "Your Command Argument Here")
'You can pass any row
'You can also skip the row parameter and get the row from Command Argument
Dim eventArgs As New GridViewCommandEventArgs(GridView1.Rows(0), GridView1, commandArgs)
GridView1_RowCommand(GridView1, eventArgs)
End Sub
Now regarding your original question, this is how you can get the selected value of DropDownList inside RowCommand event:
Edit: Fixed code to get the current row, for which the RowCommand event was raised
Protected Sub grd_Test_RowCommand(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewCommandEventArgs) Handles grd_Test.RowCommand
If e.CommandName = "Select" Then
Dim index As Integer = Convert.ToInt32(e.CommandArgument)
Dim row As GridViewRow = DirectCast(DirectCast(e.CommandSource, LinkButton).NamingContainer, GridViewRow)
Dim ddl as DropDownList = CType(row.FindControl("drp_UnAssignProp", DropDownList)
Dim selectedValue as String = ddl.Text
End If
End Sub

GridView Paging inside a repeater

I have a gridview nested within a repeater, and I'm trying to enable paging on the gridview without much success.
The gridview databound is like this
<asp:repeater....>
<asp:gridview id="GridView1" Datasource='<%# LoadData(CInt(Eval("Id"))) %>'
OnPageIndexChanging="GridViewPageIndexChanging" AllowPaging="true"
PageSize="10" ............. </asp:GridView>
</asp:repeater>
In the code behind my LoadData method get a list of objects:
Public Function LoadData(ByVal Id As Integer) As IList(Of Client)
Dim ds As IList(Of Client) = client.GetClientById(Id)
Return ds
End Function
And the event handler is as follow:
Protected Sub GridViewPageIndexChanging(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewPageEventArgs)
sender.PageIndex = e.NewPageIndex
End Sub
My code doesn't change the page in the gridview, am I missing something ?
Any help is very much appreciated.
You have to call DataBind().
Dim grid as GridView = DirectCast(sender, GridView)
grid.PageIndex = e.NewPageIndex
grid.DataBind()
EDIT
Since I can't comment yet and creating another answer to an answer makes everything confusing, I'll just edit this one.
I'm afraid the Repeater is a wrong control to use for what you want. The problem stems from the fact that it does not preserve DataItem when GridView's page events fire. So the "id" gets evaluated into nothing and subsequently a zero. Btw, in C# you'd get a null exception.
I suggest you use the DataList instead:
<asp:DataList ID="DataList" runat="server" DataKeyField="id">
<ItemTemplate>
<asp:GridView ID="Grid" runat="server"
AllowPaging="true"
PageSize="2"
OnPageIndexChanging="Grid_PageIndexChanging"
DataSource='<%# GetData(DirectCast(DataList.DataKeys(DirectCast(Container, DataListItem).ItemIndex), Integer)) %>'
>
</asp:GridView>
<hr />
</ItemTemplate>
</asp:DataList>
With code behind:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
DataList.DataSource = New Integer() {1, 2, 3, 4, 5}.Select(Function(x) New With {.id = x})
DataList.DataBind()
End If
End Sub
Protected Function GetData(ByVal id As Integer) As String()
Dim arr As String() = New String(4) {}
For i As Integer = 0 To arr.Length - 1
arr(i) = String.Format("id {0}; grid item {1}", id, i)
Next
Return arr
End Function
Protected Sub Grid_PageIndexChanging(ByVal sender As Object, ByVal e As GridViewPageEventArgs)
Dim grid As GridView = DirectCast(sender, GridView)
grid.PageIndex = e.NewPageIndex
grid.DataBind()
End Sub
This code works -- I tested. Although, personally I don't like using binding expressions.
I'm one step further ,
After I do the binding I got an exception on Eval.
I changed it in the datasource to <%#LoadData(DataBinder.Eval(Container.DataItem,"Id"))%>
I don't get the Eval exception anymore after the binding. However my grid still empty.
[update]
Ok I got it solved by keeping my Ids in hashtable and I rebind my gridview with the equivalent id from the hashtable.
It is all good now thanks everyone for your helps.
One thing I see if your markup. Your sample has the GridView directly within the Repeater control. You will need it within the ItemTemplate.
<asp:Repeater ID="rpt" runat="server" ...>
<ItemTemplate>
<asp:GridView id="gv1" runat="server" ...>
.
.
.
</asp:GridView>
</ItemTemplate>
</asp:Repeater>

Resources