How to add a table row to thead section of a gridview? - asp.net

CREATE A THEAD SECTION IN YOUR GRIDVIEW
Protected Overrides Sub OnPreRenderComplete(ByVal e As EventArgs)
If (gv.Rows.Count > 0) Then
gv.HeaderRow.TableSection = TableRowSection.TableHeader
End If
End Sub
INSERT A ROW WITH CONTENT INTO YOUR GRIDVIEW
Protected Sub gv_OnDataBound(sender As Object, e As EventArgs) Handles gv.DataBound
Dim row As New GridViewRow(0, 0, DataControlRowType.Header, DataControlRowState.Normal)
For i As Integer = 0 To gv.Columns.Count - 1
Dim cell As New TableHeaderCell()
Dim txtBx As New TextBox()
cell.Controls.Add(txtBx)
row.Controls.Add(cell)
Next
gv.HeaderRow.Parent.Controls.AddAt(1, row)
End Sub
End Class
This will insert a row with a textbox within each cell <th> at row 1.
QUESTION
How to insert a row (as in the above example) into the thead section of a gridview?
Doing this on the aspx page or in the VB is fine.

In your OnDataBound event, try setting the row you created to be in the "TableHeader" section (like you did in the PreRenderComplete event) prior to adding it to the GridView:
row.TableSection = TableRowSection.TableHeader
Since this sets the section of the table where the row belongs (header, footer, body), it should cause your row to wind up in the right place.

I couldn't find a way to do this in vb.
To apply content to the existing tr th row in the thead section you can use.
<asp:TemplateField>
<HeaderTemplate>
<p>COL TITLE</p>
<asp:TextBox ID="txBx" runat="server"/>
</HeaderTemplate>
<ItemTemplate>
CELL DATA
</ItemTemplate>
</asp:TemplateField>
Which will result in:
<thead>
<tr>
<th>
<p>COL TITLE</p>
<input id="txBx" type="text"/>
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
COL DATA
</td>
</tr>
</tbody>

Related

How to get specific value from data row while binding into a data list ? asp.net vb.net

I have a data list control, inside of it I have two tables:
<asp:DataList ID="dataListAccount" runat ="server">
<ItemTemplate >
<table runat ="server" id="tblAccountInfo">
<tr>
<td>
Account Id: <%#Eval("AccountId")%>
</td>
</tr>
</table>
<br>
<table runat="server" id ="tblAccountAmount" border="1">
<tr>
<td><%#Eval("AccountBalance", "{0:C}")%></td>
</tr>
</table>
</ItemTemplate>
</asp:DataList>
Then I populate the data list control with:
'create datatable
Dim dataTableAccount As DataTable = New DataTable()
dataTableAccount.Columns.Add("AccountID")
dataTableAccount.Columns.Add("AccountBalance")
'populate data table
Dim dataRow As DataRow = dataTableAccount.NewRow()
dataRow(0) = 1 'Account ID
dataRow(1) = 100 'Balance on the Account with Id=1
dataTableAccount.Rows.Add(dataRow)
Dim dataRow1 As DataRow = dataTableAccount.NewRow()
dataRow1(0) = 2 'Account Id
dataRow1(1) = 0 'Balance on the Account with Id=2
dataTableAccount.Rows.Add(dataRow1)
dataListAccount.DataSource = dataTableAccount
dataListAccount.DataBind()
In the event dataListAccount_ItemDataBound I want to know how can I get the "AccounId" for the current item binding.
Private Sub dataListAccount_ItemDataBound(sender As Object, e As
System.Web.UI.WebControls.DataListItemEventArgs) Handles
dataListAccount.ItemDataBound
Dim CurrentAccountId= ???????
End Sub
Better put value into label
Account Id: <asp:label id="lblAccountID" runat="server" Text ='<%#Eval("AccountId")%>' />
On code behind, you can easy to find it use
Dim CurrentAccountId = e.item.FindControl("lblAccountID")
I think I found one way to do it:
Dim currentRowBinding As System.Data.DataRowView = CType(e.Item.DataItem, System.Data.DataRowView)
Dim currentAccountId = currentRowBinding("AccountId")

Unable to Get Element with ID in VB.Net

I have the below code to retrieve the table element when the checkbox is checked.
With this, I could get the table ID. When I try to get the HtmlTable with the ID, it throws the null reference exception.
Once I get the table element with its ID, I need to loop through the rows of that table. Could anyone help me out?
ASPX.VB
Protected Sub CheckBox2_CheckedChanged(sender As Object, e As EventArgs)
Dim tab As String
Dim check As CheckBox = CType(sender, CheckBox)
tab = check.Parent.Parent.Parent.ID
Dim tabb As HtmlControl = Me.FindControl(tab)
Dim myTab As HtmlTable = CType(tabb, HtmlTable)
For Each cell As HtmlTableRow In myTab.Rows
//My Code Here
Next
End Sub
ASPX:
<table id="itemlist" class="mel-table" runat="server">
<tr>
<td>
<asp:CheckBox runat="server" ID="CheckBox2" OnCheckedChanged="CheckBox2_CheckedChanged" AutoPostBack="true" />
</td>
</tr>
</table>
Use the parent element ID under which the table is nested like below.
Protected Sub CheckBox2_CheckedChanged(sender As Object, e As EventArgs)
Dim tab As String
Dim check As CheckBox = CType(sender, CheckBox)
tab = check.Parent.Parent.Parent.ID
Dim myTab As HtmlTable = CType(mydiv.FindControl(tab), HtmlTable)
For Each cell As HtmlTableRow In myTab.Rows
//My Code Here
Next
End Sub
<div id="mydiv" runat="server">
<table id="itemlist" class="mel-table" runat="server">
<tr>
<td>
<asp:CheckBox runat="server" ID="CheckBox2" OnCheckedChanged="CheckBox2_CheckedChanged" AutoPostBack="true" />
</td>
</tr>
</table>
</div>

Trying to populate a label with text entered by a user in a repeater

I'm trying to populate labels on a repeater from what a user enters in a text box. However, the value entered in the text box isn't being picked up so nothing happens when I click the button that is to dispplay the text in the labels.
My VB code is here:
Protected Sub cmdShowCost_Click(sender As Object, e As EventArgs) Handles cmdShowCost.Click
rptProducts.DataBind()
Dim someString As String
Dim txtField As TextBox
Dim lblField As Label
Dim j As Integer = 0
For Each item In rptProducts.Items
txtField = CType(item.FindControl("txtAmountToBuy"), TextBox)
lblField = CType(item.FindControl("lblCost"), Label)
If Not IsNothing(txtField) Then
j = j + 1
someString = txtField.Text
lblField.Text = someString
Else
lblField.Text = 0
End If
Next
End Sub
and my html is here:
<div>
<table>
<asp:Repeater ID="rptProducts" runat="server" >
<HeaderTemplate>
<tr>
<td>
Product Name
</td>
</td>
<td>
Price per Kg
</td>
<td>
Kg in Stock
</td>
<td>
Action
</td>
<td>
Amount to Buy
</td>
<td>
Cost
</td>
</tr>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td>
<%#Eval("Product")%>
</td>
<td>
<%#Eval("PricePerKg")%>
</td>
<td>
<%#Eval("QuantityKg")%>
</td>
<td>
<a href='amount.aspx?ProductID=<%# DataBinder.Eval(Container.DataItem, "ProductID")%>&Stock=<%#Eval("QuantityKg")%>'>Details...</a>
</td>
<td>
<asp:TextBox ID="txtAmountToBuy" runat="server"/>
</td>
<td>
<asp:Label runat="server" ID="lblCost" />
</td>
</tr>
</ItemTemplate>
<FooterTemplate></FooterTemplate>
</asp:Repeater>
</table>
</div>
The rest of the repeater works fine, it's just the populating the labels that doesn't work.
This is my first time posting a question, hopefully someone can help. I searched as best I could for this problem but nothing seemed to work.
Thanks.
Two thing you need to take care of:
1.In page_Load you need to make sure that you are not binding the repeater in PostBack:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
rptProducts.DataSource = GetProducts() 'Or whatever datasource you have
rptProducts.DataBind()
End If
End Sub
2.In click method of the cmdShowCost button, don't bind the repeater (As mentioned by ajakblackgoat ) :
Protected Sub cmdShowCost_Click(sender As Object, e As EventArgs) Handles cmdShowCost.Click
'rptProducts.DataBind()
Dim someString As String
Dim txtField As TextBox
Dim lblField As Label
Dim j As Integer = 0
For Each item In rptProducts.Items
txtField = CType(item.FindControl("txtAmountToBuy"), TextBox)
lblField = CType(item.FindControl("lblCost"), Label)
If Not IsNothing(txtField) Then
j = j + 1
someString = txtField.Text
lblField.Text = someString
Else
lblField.Text = 0
End If
Next
End Sub

Hiding a table row (the ItemPlaceholderID row) in a ListView

I have a table row that holds my paging controls in a ListView as follows (partial layout):
<asp:ListView ID="lvOrderItems" runat="server"
DataSourceID="odsShoppingCart"
DataKeyNames="ProductNumber"
ItemPlaceholderID="lvItemContainer">
<LayoutTemplate>
<table id="lvCart" runat="server">
<tr id="lvHeader" runat="server">
...
</tr>
<tr id="lvItemContainer" runat="server"></tr>
<tr id="lvPaging" runat="server">
...
</tr>
</table>
</LayoutTemplate>
In my code-behind, I handle the DataBound event as follows, and I am planning on hiding the entire lvItemContainer row conditionally (for now, I am just trying to hide the row itself without conditions):
Protected Sub lvOrderItems_DataBound(ByVal sender As Object, ByVal e As EventArgs) Handles lvOrderItems.DataBound
Dim lvItemContainer As HtmlTableRow = CType(lvOrderItems.FindControl("lvItemContainer"), HtmlTableRow)
If Not lvItemContainer Is Nothing Then
Response.Write("hit1")
lvItemContainer.Visible = False
End If
Dim lvPaging As HtmlTableRow = CType(lvOrderItems.FindControl("lvPaging"), HtmlTableRow)
If Not lvPaging Is Nothing Then
Response.Write("hit2")
lvPaging.Visible = False
End If
End Sub
So when this runs on DataBound, hit1 is never fired, but hit2 is... any ideas what is happening here?
HTML purists don't like it, but this approach works:
In the OnLayoutCreated event, try one of the following approaches:
Take the runat="server" out of the table and child rows, and do this:
<asp:Panel ID="pnlItemContainer" runat="server">
<tr id="lvItemContainer"></tr>
</asp:Panel>
pnlItemContainer.Visible = false;
Or you can do this:
<tr id="lvItemContainer" runat="server"></tr>
EDIT: Embedded style element because setting visible to false does not work in the layout template.
lvItemContainer.Style["display"] = "none";
I'm not sure how it will work with a layout template, but it's worked for me in other situations.
Instead of attempting to (unsuccessfully) adjust the visibility of the ItemPlaceholderID container, I've set the visibility of the individual rows in the container.

How can I add group heading rows to a data bound GridView

I have a GridView with three databound columns, like this:
<Columns>
<asp:BoundField HeaderText="Type" DataField="Type" />
<asp:BoundField HeaderText="Amenity" DataField="Amenity" />
<asp:BoundField HeaderText="Distance" DataField="Distance" DataFormatString="{0:0.00} Km" />
</Columns>
Records are sorted by type, and I want to remove the Type column, but then insert a header row for each type when the value of type for the next set of rows changes. How can I do this?
This is not the prettiest, but it solves the problem without going outside of the GridView paradigm. Thanks to carlj for Adding (or Inserting) Subheader Rows into a Gridview
Dim _currentAmenityType = String.Empty
Protected Sub amenitiesGrid_RowDataBound(ByVal sender As Object, ByVal e As GridViewRowEventArgs) Handles amenitiesGrid.RowDataBound
If (e.Row.RowType = DataControlRowType.DataRow) Then
Dim drv = e.Row.DataItem
If (drv("Type") <> _currentAmenityType) Then
_currentAmenityType = drv("Type")
Dim parentTable = TryCast(e.Row.Parent, Table)
If Not parentTable Is Nothing Then
Dim row = New GridViewRow(-1, -1, DataControlRowType.DataRow, DataControlRowState.Normal)
Dim cell = New TableCell()
cell.ColumnSpan = amenitiesGrid.Columns.Count
cell.Width = Unit.Percentage(100)
cell.Style.Add("font-weight", "bold")
cell.Style.Add("background-color", "#c0c0c0")
cell.Style.Add("color", "white")
Dim span = New HtmlGenericControl("span")
span.InnerHtml = _currentAmenityType
cell.Controls.Add(span)
row.Cells.Add(cell)
parentTable.Rows.AddAt(parentTable.Rows.Count - 1, row)
End If
End If
End If
End Sub
With the standard GridView control, I believe that you cannot dynamically add extra rows once the control has been databound, so you would need to alter the datasource prior to databinding. However, this probably isn't a very good solution to what you need.
I think that using the GridView control might not be your best option in this situation, as the HTML that is rendered would be
<table>
<thead>
<tbody>
So adding extra "header" rows between rows wouldn't actually be Header rows. They would simply be an extra row <tr><td>. Knowing this, I think that you might be better using a Repeater control, building up the HTML for the table within the control, and then have a Placeholder within the Content Template which you can use to mimic adding a new Row.
e.g.
<table>
<asp:Repeater ID="rpt1" runat="server">
<HeaderTemplate>
<thead>
<tr>
<th> </th>
<th>Amenity</th>
<th>Distance</th>
</tr>
</thead>
<tbody>
</HeaderTemplate>
<ItemTemplate>
<asp:PlaceHolder id="phRow" runat="server" />
<tr>
<td> </td>
<td>Amenity Value</td>
<td>Distance Value</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</tbody>
</FooterTemplate>
</asp:Repeater>
</table>
In your code, loop through each Item in the Repeater. If the Type is different, then add a Literal to the Placeholder in that Row.
Literal lt = new Literal() { Text = "<tr><td colspan='3'>Type Value</td></tr>" };

Resources