Getting text from labels inside gridview cells (VB) - asp.net

VB
I've got a gridview in which I need to use template columns, therefore instead of being able to retrieve text straight from the cell, it's inside of a label. All the labels have different ids as well so I would like to programmatically retrieve the label inside a cell then look at the text inside the label.
This is what I have got at the moment, however it never manages to return the text and instead returns the empty string ("").
Public Function ReturnLabelText(ByVal c As TableCell) As String
For Each lb In c.Controls
If lb.[GetType]() = GetType(Label) Then
Return CType(lb, Label).Text()
End If
Next
Return ""
End Function
The function is called on this line:
doc.ReplaceText("#" + gridView.HeaderRow.Cells(i).Text.ToLower, ReturnLabelText(row.Cells(i)).Replace(" ", "").Replace(vbCr, ""))

You have to use GridViewRow.FindControl("ControlID") to get the reference of the Label.
So for example, if you want to loop loop all rows:
For Each row As GridViewRow In Me.GridView1.Rows
Dim label = DirectCast(row.FindControl("LabelID"), Label)
Dim text As String = label.Text
' ... '
Next
But if you want to set it's text on databinding i'd use the GridView.RowDataBound event instead:
Protected Sub GridView1_RowDataBound(sender As Object, e As GridViewRowEventArgs) Handles GridView1.RowDataBound
Select Case e.Row.RowType
Case DataControlRowType.DataRow
Dim label = DirectCast(e.Row.FindControl("LabelID"), Label)
Dim text As String = label.Text
' ... '
End Select
End Sub
You can even get the DataSource of each row via e.Row.DataItem to access all fields.
If you have a TableCell and you want to get all labels in it you could also use OfType:
Dim firstLabel = c.Controls.OfType(Of Label)().FirstOrDefault()
If firstLabel IsNot Nothing Then Return firstLabel.Text
Return Nothing

Related

Need to display total price in gridview

just been trying to display my total price from a column in my footer row.
here is my code to try that but it doesnt seem to be even going through it when i put a break point in
Sub gvPayments_RowDataBound(ByVal sender As Object, ByVal e As GridViewRowEventArgs)
If e.Row.RowType = DataControlRowType.DataRow Then
' add the UnitPrice and QuantityTotal to the running total variables
invoiceTotal += Convert.ToDecimal(DataBinder.Eval(e.Row.DataItem, "Total"))
ElseIf e.Row.RowType = DataControlRowType.Footer Then
e.Row.Cells(0).Text = "Total:"
' for the Footer, display the running totals
e.Row.Cells(5).Text = invoiceTotal.ToString("c")
e.Row.Cells(5).HorizontalAlign = HorizontalAlign.Right
e.Row.Font.Bold = True
End If
End Sub
If you need any more of my code, just ask!
I like to use a method that doesn't require handling any events. It just uses a TemplateField and a couple different functions. In your GridView, make the column like this:
<asp:TemplateField HeaderText="Total">
<ItemTemplate><%#DisplayAndAddToTotal(Eval("Total").ToString(), "Total")%></ItemTemplate>
<FooterTemplate><%#GetTotal("Total")%></FooterTemplate>
</asp:TemplateField>
The second parameter to DisplayAndAddToTotal can be any string you want as long as you use the same string in GetTotal. I usually just use the field name again though. Here are the two functions used, DisplayAndAddToTotal and GetTotal. They use a Hashtable to store the totals so that it works with any number of columns you want to add up. And they also work with counting the number of "True"s for a Boolean field.
Protected total As Hashtable = New Hashtable()
Protected Function DisplayAndAddToTotal(itemStr As String, type As String) As Double
Dim item As Double
If itemStr = "True" Then
item = 1
ElseIf Not Double.TryParse(itemStr, item) Then
item = 0
End If
If total.ContainsKey(type) Then
total(type) = Double.Parse(total(type).ToString()) + item
Else
total(type) = item
End If
Return item
End Function
Protected Function GetTotal(type As String) As Double
Try
Dim result As Double = Double.Parse(total(type).ToString())
Return result
Catch
Return 0
End Try
End Function

asp.net vb.net gridview, get row id when pressing template field button

I have a template field with a button. I want to press the button and get the row Id so I can return the users selection. I have a regular select button which works fine but the user want the people who are not employee’s to hide the select button. I have this working but since it’s a template field it fires the RoW_command procedure and I cannot seem to get the row index since it is a template field and not the regular Select button. Or I cannot seem to name the Regular select button since it Command field does not have a Name or ID property?
Like I said this works hiding the template field called btnSelect
Private Sub GridView3_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles GridView3.RowDataBound
If e.Row.RowType = DataControlRowType.DataRow Then
If (DataBinder.Eval(e.Row.DataItem, "LegacyPersonType") <> "Employee") Then
e.Row.ForeColor = Drawing.Color.Black
e.Row.BackColor = Drawing.Color.Yellow ' This will make row back color yellow
e.Row.FindControl("btnSelect").Visible = False
Else
e.Row.ForeColor = Drawing.Color.Black
e.Row.BackColor = Drawing.Color.White ' the normal employees make white
End If
End If
End Sub
I need to find the Row index when I press btnSelect
Private Sub GridView3_RowCommand(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewCommandEventArgs) Handles GridView3.RowCommand
Dim index As Integer = Convert.ToInt32(e.CommandArgument) ‘ Error invalid
‘ in other words when pressing the tem-plate field there is no e.CommandArgument
‘But clicking the regular select there is
Dim row As GridViewRow = GridView3.Rows(index)
Session("EnterpriseID") = HttpUtility.HtmlDecode(GridView3.Rows(index).Cells(2).Text)
Dim EmployeeType As String = HttpUtility.HtmlDecode(GridView3.Rows(index).Cells(7).Text)
Dim CommonName As String = HttpUtility.HtmlDecode(GridView3.Rows(index).Cells(1).Text)
Dim EnterpriseID = HttpUtility.HtmlDecode(GridView3.Rows(index).Cells(6).Text)
The GridViewRow object knows its row index via the RowIndex property in the RowCommand event, like this:
Private Sub GridView3_RowCommand(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewCommandEventArgs) Handles GridView3.RowCommand
' Get the row by finding the grandparent of the control (button)
' that initiated the command
Dim theGridViewRow As GridViewRow
theGridViewRow = CType(CType(e.CommandSource, Button).Parent.Parent, GridViewRow)
' Get the index value from the grid view row
Dim index As Integer = theGridViewRow.RowIndex
End Sub
Ok I figured it out myself, I made the default Select button on the grid a Template field. since it was the default button it had the necessary code to make it fire. This was the problem with making a template field from scratch. And by making it a template field it then also gave it a name. So in the RowDataBound code the FindControl method above hides it when a person is not an employee. – R2 Builder 1 min ago edit

asp.net looping through dynamic control in a table

i have a table which contains questions and a bunch of dynamically created radio button lists, i m trying to write code which will loop through each one of the radio button list and get the value of the selected question value and corresponding question id . i have the following code which returns the selected radio button list value.how i will get questions ids as well as their selected value?
For Each ctrl As Control In form1.Controls
If TypeOf ctrl Is RadioButtonList Then
Dim rbl As RadioButtonList = DirectCast(ctrl, RadioButtonList)
For i As Integer = 0 To rbl.Items.Count - 1
If rbl.Items(i).Selected Then
Dim value As String = rbl.SelectedValue
End If
Next
End If
Next
When creating the radio buttons you should put them into a dictionary (make sure to do so in the Init phase). The String key is assumed to hold the question id:
Dim radios As New Dictionary(Of String, RadioButtonList)
Dim table As DataTable
Sub Page_Init(sender As Object, e As EventArgs)
table = ...
For Each row As DataRow In table.Rows
Dim rbl As New RadioButtonList
' add radio buttons to rbl
radios.Add(row("id").ToString, rbl)
Next
End Sub
Then in the event handler for retrieving the answers you can easily access them:
Sub MyHandler(sender As Object, e As EventArgs)
For Each row As DataRow In table.Rows
Dim value As String = GetAnswer(row("id").ToString)
' do something with the answer ...
Next
End Sub
Function GetAnswer(id As String) As String
For Each item In radios(id)
If item.Selected Then Return item.SelectedValue
Next
Return Nothing
End Function

get value of label when button clicked in nested repeater asp.net vb

I have nested repeaters, each item in the nested repeater has a label and a button on it, i want to beable to access the label.text when the button is clicked, I think i'm nearly there as I can return the index of the repeater and nested repeater that is clicked, i'm just having some trouble finding the label itself.
You might be able to help me without me posting the repeater code. Here is my code behind for when the button is clicked.
Protected Sub btnEditUser_Click(ByVal sender As Object, ByVal e As System.EventArgs)
Dim btnEditUser As Button = DirectCast(sender, Button)
Dim reClient As RepeaterItem = DirectCast(btnEditUser.NamingContainer.Parent.Parent, RepeaterItem)
Dim reUser As RepeaterItem = DirectCast(btnEditUser.NamingContainer, RepeaterItem)
Dim selectedClient As Integer = reClient.ItemIndex
Dim selectedUser As Integer = reUser.ItemIndex
Dim UserId As Label = DirectCast(reClients.Items(selectedClient).FindControl("lUserName"), Label)
Response.Write(selectedClient & " " & selectedUser & " " & UserId.Text)
End Sub
I'm currently getting this error 'Object reference not set to an instance of an object.' when trying to write the value of UserId.Text so i think i've got it slightly wrong in this line:
Dim UserId As Label = DirectCast(reClients.Items(selectedClient).FindControl("lUserName"), Label)
This is just a guess, but sometimes you get errors like this when not all rows contain the control you're looking for. Often the code loops through the rows in order, hits a header row first that doesn't contain the relevant control, and fails.
Here is a good MSDN article - Locating a Control Inside a Hierarchy of Naming containers.
Private Function FindControlRecursive(
ByVal rootControl As Control, ByVal controlID As String) As Control
If rootControl.ID = controlID Then
Return rootControl
End If
For Each controlToSearch As Control In rootControl.Controls
Dim controlToReturn As Control =
FindControlRecursive(controlToSearch, controlID)
If controlToReturn IsNot Nothing Then
Return controlToReturn
End If
Next
Return Nothing
End Function
Try it,
Dim UserId As Label =DirectCast(FindControlRecursive(repClient,"lUserName"),Label)

Gridview Header with sort-icon

I am binding a data set to a GridView in VB .net. I have some custom sorting setup, and want to display an icon next to the header if one of my 3 options is selected.
I've read a lot of methods in doing this, and I see Gridviews even have a ASC and DESC header style I can associate with the view. I have 2 problems with this, though:
I am sorting a List with linq on Sort Trigger, then binding it to the datagrid.
The reason I do it this way, is I want to maintain multiple sort levels, ordering by 3 columns rather than 1.
Edit for clarity
Specifically what I want to do is loop through the value of a GridView's Header text, see if it matches what I have saved in viewstate, and if so add an image for that header in particular. Something essentially like below, however headerRow.Cells(y).Text is always returning "", even when the header has text:
Sub gvPatronData_RowCreated(ByVal sender As Object, ByVal e As GridViewRowEventArgs)
Dim savedSortDirection(), savedSortColumn() As String
Dim headerRow As GridViewRow = gvPatronData.HeaderRow
'this sets the values of these variables
'as strings equal to the text displayed in the header of the gridview
_patronBl.SplitPatronSort(savedSortDirection, SortDirection, savedSortColumn, SortColumn)
If SortDirection <> "" Then
If e.Row.RowType = DataControlRowType.Header Then
For x = 0 To savedSortDirection.Length - 1
For y = 0 To headerRow.Cells.Count - 1
If headerRow.Cells(y).Text = savedSortColumn(x) Then
If savedSortDirection(x) = "Ascending" Then
Dim bGStyle As New System.Web.UI.WebControls.Style()
bGStyle.CssClass = "upSort"
headerRow.Cells(y).ApplyStyle(bGStyle)
Else
Dim bGStyle As New System.Web.UI.WebControls.Style()
bGStyle.CssClass = "downSort"
headerRow.Cells(y).ApplyStyle(bGStyle)
End If
End If
Next
Next
End If
End If
End Sub
Have you tried to loop the GridView's Columns instead of the the GridViewRow's Cell-Collection? A DataControlField has a HeaderText property.
For Each col As DataControlField In gvPatronData.Columns
If col.HeaderText = savedSortColumn(x) Then
If savedSortDirection(x) = "Ascending" Then
Dim bGStyle As New System.Web.UI.WebControls.Style()
bGStyle.CssClass = "upSort"
headerRow.Cells(gvPatronData.Columns.IndexOf(col)).ApplyStyle(bGStyle)
Else
Dim bGStyle As New System.Web.UI.WebControls.Style()
bGStyle.CssClass = "downSort"
headerRow.Cells(gvPatronData.Columns.IndexOf(col)).ApplyStyle(bGStyle)
End If
End If
Next
This is how I ended up doing it. Actually drilling into the table objects was where I was coming up short before.
Sub gvPatronData_RowDataBound(ByVal sender As Object, ByVal e As GridViewRowEventArgs)
Dim savedSortDirection(), savedSortColumn() As String
Dim columnCollection As DataControlFieldCollection = gvPatronData.Columns
_patronBl.SplitPatronSort(savedSortDirection, SortDirection, savedSortColumn, SortColumn)
If e.Row.RowType = DataControlRowType.Header Then
For x = 0 To savedSortDirection.Length - 1
For Each col As DataControlField In columnCollection
If col.HeaderText = _headerDictionary(savedSortColumn(x)) Then
If savedSortDirection(x) = "Ascending" Then
e.Row.Cells(gvPatronData.Columns.IndexOf(col)).Attributes.Add("Style", _
"background-image: url(images/arrow_up.png);background-repeat:no-repeat;background-position: 96% 50%;")
Else
e.Row.Cells(gvPatronData.Columns.IndexOf(col)).Attributes.Add("Style", _
"background-image: url(images/arrow_down.png);background-repeat:no-repeat;background-position: 96% 50%;")
End If
End If
Next
Next
End If
_headerDictionary : This was a dictionary of my DataField to HeaderText strings, since my savedSortColumn was the data field to sort on.
Def:
Public Function ColumnDataFieldToHeaderTextDictionary() As Dictionary(Of String, String)
Dim dict As New Dictionary(Of String, String)
dict.Add("FirstName", "First Name")
dict.Add("LastName", "Last Name")
dict.Add("Phone", "Phone Number")
dict.Add("Phone2", "Alternate Phone Number")
dict.Add("Email", "Email")
Return dict
End Function

Resources