How to find a control inside a TemplateField in Gridview - asp.net

I have a gridView with a textBox inside a templateField. I wan to extract the text of the textBox if a checkbox is marked in the row.
I have the gridView defined as follows
<asp:GridView ID="GV_Comments" runat="server" AutoGenerateColumns="False" DataKeyNames="id"
DataSourceID="SQL_Comments">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:CheckBox runat="server" ID="Comment_Select" />
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="ID" HeaderText="ID" ReadOnly="True" SortExpression="ID" />
<asp:TemplateField HeaderText="comment" SortExpression="comment">
<ItemTemplate>
<asp:Label ID="Label1" runat="server" Text='<%# Bind("comment") %>'></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="CommentForPeriod" runat="server" Text='<%# Bind("comment") %>'></asp:TextBox>
</EditItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
<asp:Button ID="B_Load" runat="server" Text="Transfer Selection" onclick="B_Load_Click" />
<br />
<asp:TextBox ID="CompiledText" runat="server" Width="662px" Rows="10"
TextMode="MultiLine"></asp:TextBox>
And the code as follows
Protected Sub B_Load_Click(ByVal sender As Object, ByVal e As EventArgs) '(sender As Object, e As System.EventArgs) Handles B_Load.Click
Dim FullText As String = ""
For Each row As GridViewRow In GV_Comments.Rows
Dim CB_Control As CheckBox = CType(row.FindControl("Comment_Select"), CheckBox)
Dim Txt_Control As TextBox = CType(row.FindControl("CommentForPeriod"), TextBox)
If CB_Control IsNot Nothing AndAlso CB_Control.Checked AndAlso Txt_Control IsNot Nothing Then
FullText = FullText & Txt_Control.Text & "<br/>"
End If
Next row
CompiledText.Text = FullText.ToString
End Sub
When I debug the code I can see that the Checkbox control is found but not the TextBox control. Would anyone see why?

You can't do like this. When you click the button: B_Load, then GridView is NOT in Edit mode. And this is why you can't get the TextBox, which is in EditItemTemplate.
You can only get the controls inside <ItemTemplate> in your button click as gridview is in Normal display Mode. <EditItemTemplate> controls are rendered only when GridView enters Edit mode.
So, you need to get the value of the Label: Label1 here actually, which has the same value and is inside <ItemTemplate> .
Dim Lbl_Control As Label= CType(row.FindControl("Label1"), Label)
// button click as usual, just get and check the value of Label control, rather than TextBox control.
Protected Sub B_Load_Click(ByVal sender As Object, ByVal e As EventArgs) '(sender As
Object, e As System.EventArgs) Handles B_Load.Click
Dim FullText As String = ""
For Each row As GridViewRow In GV_Comments.Rows
Dim CB_Control As CheckBox = CType(row.FindControl("Comment_Select"),
CheckBox)
Dim Lbl_Control As Label= CType(row.FindControl("Label1"), Label)
If CB_Control IsNot Nothing AndAlso CB_Control.Checked AndAlso Lbl_Control
IsNot Nothing Then
FullText = FullText & Lbl_Control.Text & "<br/>"
End If
Next row
CompiledText.Text = FullText.ToString
End Sub

Related

Conditional render on a gridview

I have this GridView:
<asp:GridView CssClass="table table-hover mt-5" ID="OrderTable" runat="server" AutoGenerateColumns="False" DataKeyNames="Identificativo" DataSourceID="DBGestioneOrdini" OnPreRender="GridView_PreRender">
<Columns>
<asp:BoundField DataField="Identificativo" HeaderText="Identificativo" InsertVisible="False" ReadOnly="True" SortExpression="Identificativo" />
<asp:TemplateField HeaderText="Genera Fattura" HeaderStyle-CssClass="text-center" ItemStyle-VerticalAlign="Middle" ItemStyle-HorizontalAlign="Center">
<ItemTemplate>
<asp:LinkButton type="button" ID="generateInvoiace" runat="server" OnClick="generateInvoiace_Click" ForeColor="Black" CommandName="SelectRow" CommandArgument='<%# Eval("Identificativo") %>'>
<i class="fa-solid fa-file-invoice-dollar fa-lg>
</i>
</asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
It takes the data from an Order Table. The problem here is that I need to disable the clickable icon for every record which have a specific value on a field of the db ... I can't actually realize how can i modify only certain icons since the table is rendered by asp.net and not manually
Ok, so say we have this grid view:
<asp:GridView ID="GHotels" runat="server" AutoGenerateColumns="False"
DataKeyNames="ID" CssClass="table">
<Columns>
<asp:BoundField DataField="FirstName" HeaderText="FirstName" />
<asp:BoundField DataField="LastName" HeaderText="LastName" />
<asp:BoundField DataField="HotelName" HeaderText="HotelName" />
<asp:TemplateField>
<ItemTemplate>
<asp:CheckBox ID="chkActive" runat="server" Checked='<%# Eval("Active") %>' />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Hotel Information" ItemStyle-HorizontalAlign="Center">
<ItemTemplate>
<asp:Button ID="cmdView" runat="server" Text="Info" CssClass="btn"
OnClick="cmdView_Click" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
And our code to load the grid view could be this:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
LoadGrid
End If
End Sub
Sub LoadGrid()
Dim rstData As DataTable
rstData = MyRst("SELECT * FROM tblHotelsA ORDER BY HotelName")
GHotels.DataSource = rstData
GHotels.DataBind()
End Sub
Public Function MyRst(strSQL As String) As DataTable
Dim rstData As New DataTable
Using conn As New SqlConnection(My.Settings.TEST4)
Using cmdSQL As New SqlCommand(strSQL, conn)
conn.Open()
rstData.Load(cmdSQL.ExecuteReader)
rstData.TableName = strSQL
End Using
End Using
Return rstData
End Function
So no loops, just send a data table to the grid, and we now have this:
However, lets say we ONLY want the info button to show for when the hotel is active.
so, for things like totals, time formatting, color formatting, or whatever?
You use the row data bound event.
So, we can add to above this event that will "hide" the info button for any row in which the hotel is not active.
So, this code:
Protected Sub GHotels_RowDataBound(sender As Object, e As GridViewRowEventArgs) Handles GHotels.RowDataBound
If e.Row.RowType = DataControlRowType.DataRow Then
Dim chkActive As CheckBox = e.Row.FindControl("chkActive")
Dim cmdView As Button = e.Row.FindControl("cmdView")
If chkActive.Checked = False Then
' hide the info button
cmdView.Style.Add("display", "none")
End If
End If
End Sub
So, as noted, for running totals, highlght a row, color a row - or in this simple case hide/show the info button based on active column?
(and note you are NOT limited to just the controls on that row - you have full use of the whole database row if you wish durng the binding).
And we now see/get this:
And note once again, no looping or for next code.

Multiple delete wont work (asp.net vb)

code sample aspx vb behind code:
Protected Sub btnDelete_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnDelete.Click
For Each row As GridViewRow In GridView1.Rows
Dim checkbox As CheckBox = CType(row.FindControl("chkdelete"), CheckBox)
If checkbox.Checked Then
Dim ID As Integer = Convert.ToInt32(GridView1.DataKeys(row.RowIndex).Value)
SqlDataSource1.DeleteParameters("ID").DefaultValue = ID.ToString()
SqlDataSource1.Delete()
End If
Next row
front code :
`
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:CheckBox ID="chkdelete" runat="server" />
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="ID" HeaderText="No"
SortExpression="ID"/>
<asp:BoundField DataField="Name" HeaderText="Name"
SortExpression="Name"/>
<asp:CommandField Headertext="Edit" ShowEditButton="True" />
<asp:CommandField Headertext="Delete" ShowDeleteButton="True" />
</Columns>
</asp:GridView>
<asp:Button ID="btnDelete" runat="server" Text="Delete" onclick="btnDelete_Click"/>`
my question is, why my multiple delete still wont work? whats wrong with my code? anyone pls help..
Protected Sub btnDelete_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnDelete.Click
For Each row As GridViewRow In GridView1.Rows
Dim checkbox As CheckBox = CType(row.FindControl("chkdelete"), CheckBox)
If checkbox.Checked Then
Dim ID As Integer = Convert.ToInt32(GridView1.DataKeys(row.RowIndex).Value)
Delete(ID)
End If
Next row
End Sub
Public Function Delete(ByRef ID as Integer)
' Your Connection Coding comes here
SqlDataSource1.DeleteParameters("ID").DefaultValue = ID.ToString()
SqlDataSource1.Delete()
End Function
Try This Way..!!

GridView Edit Button Requires 2 Clicks

When pressing edit button in gridview, edit template is displayed only after 2 clicks.
And another problem: Value of the field to edit is displayed in gridview initially, but not in edit template.
Asp code:
<asp:GridView ID="GridView1" runat="server" AllowPaging="True" AllowSorting="True"
AutoGenerateColumns="False" CellPadding="4" OnRowEditing="EditRow"
OnRowCancelingEdit="CancelEditRow" DataKeyNames="AREA" DataMember="DefaultView">
<Columns>
<asp:BoundField DataField="AREA" HeaderText="AREA" ReadOnly="True"
SortExpression="AREA" />
<asp:TemplateField HeaderText="LEADER_USER" SortExpression="LEADER_USER">
<ItemTemplate><%#Eval("leader_user")%></ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="txtleaderuser" runat="server" Text='<%#Eval("leader_user")%>'/>
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<ItemTemplate>
<asp:ImageButton ID="editButton" runat="server" CommandName="Edit"
ImageUrl="images/pencil1.png" Text="Edit" ToolTip="Edit" />
</ItemTemplate>
<EditItemTemplate>
<asp:Button ID="BtnUpdate" runat="server" CommandName="Update"
Text="Update" />
<asp:Button ID="BtnCancel" runat="server" CommandName="Cancel"
Text="Cancel" />
</EditItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
vb code:
Protected Sub EditRow(ByVal sender As Object, ByVal e As GridViewEditEventArgs)
GridView1.EditIndex = e.NewEditIndex
GridView1.DataSource = SqlDataSource1
'If Not IsPostBack Then
'GridView1.DataSourceID = SqlDataSource1.ID
'GridView1.DataBind()
'End If
End Sub
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
SqlDataSource1.SelectCommand = "SQL"
SqlDataSource1.ConnectionString = "My conn string"
If Not IsPostBack Then
'GridView1.DataSourceID = SqlDataSource1.ID
GridView1.DataSource = SqlDataSource1
GridView1.DataBind()
End If
End Sub
I think you need to call DataBind to rebind the data source. You've commented it out, but it looks like you had it in a IsPostBack block, which would only execute on the initial page load.
Try:
Protected Sub EditRow(ByVal sender As Object, ByVal e As GridViewEditEventArgs)
GridView1.EditIndex = e.NewEditIndex
GridView1.DataSource = SqlDataSource1
GridView1.DataBind()
End Sub

How to Update dataset and backend sql table from Gridview data without for loop?

In ASP.NET i have GridView as
<asp:GridView ID="GV" runat="server" AutoGenerateColumns="false">
<Columns>
<asp:TemplateField HeaderText="Name">
<ItemTemplate>
<asp:TextBox ID="txtName" runat="server" Text='<%#Eval("Name") %>'></asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="EmailId" HeaderText="Email" />
</Columns>
</asp:GridView>
<asp:Button ID="btnSubmit" runat="server" Text="Update Changes to Dataset" />
here is my code behind to bind the data on page load
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
Dim str As String = ConfigurationManager.ConnectionStrings("DBCon").ConnectionString
Dim Conn As New SqlConnection(str)
Conn.Open()
Dim qry As String = "SELECT Name,EmailId FROM dbo.Employee"
Dim adp As New SqlDataAdapter(qry, Conn)
Dim ds As New DataSet
adp.Fill(ds)
GV.DataSource = ds
GV.DataBind()
End If
End Sub
Now in my Gridview i have bind Name to Textbox and those textboxes are editable for client
I have plenty of records to show on gridview
Now what i want is that on a click of submit button updated data to be appeared in a dataset without using any kind of for loop
And i also want the updated data to be reflected at backend Employee table
Suggest if you have any tricks

GridView RowDataBound event handler does not find GridView cells content

I have the following GridView, which has as DataSource a List<T>:
<asp:GridView ID="gvDownloads" UseAccessibleHeader="False"
AutoGenerateColumns="False" runat="server" PageSize="10" AllowPaging="true"
CellPadding="4" CellSpacing="1" GridLines="None" DataKeyNames="productid">
<EmptyDataTemplate>
No licenses found
</EmptyDataTemplate>
<Columns>
<asp:TemplateField HeaderText="Id" >
<ItemTemplate>
<%# Eval("ProductId")%>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Product Name">
<ItemTemplate>
<%# Eval("ProductName")%>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Stock Code">
<ItemTemplate>
<%# Eval("StockCode")%>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Which renders correctly and with the proper values.
Now, I would like to modify on the fly the field StockCode and in order to do so I have in my code behind:
Sub gvDownloads_RowDataBound(ByVal sender As Object, ByVal e As GridViewRowEventArgs) Handles gvDownlads.RowDataBound
If e.Row.RowType = DataControlRowType.DataRow Then
e.Row.Cells(2).Text = StockCodeConverter.Convert(e.Row.Cells(2).Text)
End If
End Sub
But the data cells corresponding to StockCode are empty. Now I tried to debug and for some reason the code finds just the value of the header row. The values of the other rows are string.Empty or &nsbp. Might it depend on the List as DataSource?
Use ASP.NET controls instead, for example Labels:
If e.Row.RowType = DataControlRowType.DataRow Then
Dim lblStockCode = DirectCast(e.Row.FindControl("lblStockCode"), Label)
lblStockCode.Text = StockCodeConverter.Convert(lblStockCode.Text)
End If
on aspx:
<asp:TemplateField HeaderText="Stock Code">
<ItemTemplate>
<asp:Label Id="LblStockCode" runat="server" Text='<%# Eval("StockCode") %>'></asp:label>
</ItemTemplate>
</asp:TemplateField>
You can even omit the Eval on aspx and set the Text property completely in codebehind:
If e.Row.RowType = DataControlRowType.DataRow Then
Dim row = DirectCast(e.Row.DataItem, DataRowView)
Dim lblStockCode = DirectCast(e.Row.FindControl("lblStockCode"), Label)
lblStockCode.Text = StockCodeConverter.Convert(row["StockCode"].ToString)
End If
Edit: If you want to stay with your text and also with the TemplateField you could cast the first control in the cell which is a autogenerated DataBoundLiteralControl when there's only text and use it's Text property.
Dim StockCode = DirectCast(e.Row.Cells(2).Controls(0), DataBoundLiteralControl).Text
But that makes your code less readable in my opinion.
I think in GridView RowDataBound Event as the Binding is still in process you are not getting any Value...I would suggest you to use "DataRowView"
DataRowView drv = (DataRowView)e.Row.DataItem;
e.Row.Cells(2).Text = drv["StockCode"].ToString();

Resources