When I call gvTags.DataSource = GetTags() and gvTags.DataBind() it shows that all the rows and columns have the appropriate data.
When the OnRowDataBound function is hit, the last columns in my first table row have no data (null values).
The only difference between this table and the others I've created is that I am showing/hiding columns based on a user selection higher in the page. But - the showing/hiding is done within the OnRowDataBound function, where the data is already missing. I have no idea what's going on, or where to even start for looking further.
UPDATE: It looks like the problem is caused by the last three lines of the RowDataBound function. When I remove those three rows, the data displays as it should. So - I need a way to show/hide those three columns based on if a user selects a checkbox elsewhere on the page (Include Removed Entries). If the checkbox is selected, the RemovedBy and RemovedDate columns are visible. If it is not selected, those hide but the Description column is visible.
<asp:GridView ID="gvTags" CssClass="table table-striped" runat="server" AutoGenerateColumns="false"
AllowSorting="false" GridLines="None" OnRowDataBound="gvTags_RowDataBound" DataKeyNames="TagID">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton ID="btnRemove" runat="server" OnClick="btnRemove_Click">
Remove
</asp:LinkButton>
<asp:LinkButton ID="btnReapply" runat="server" OnClick="btnReapply_Click">
Re-Apply
</asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="TagID" HeaderText="ID" />
<asp:BoundField DataField="InstalledBy" HeaderText="Installed By" />
<asp:BoundField DataField="InstalledDate" HeaderText="Date Installed" />
<asp:BoundField DataField="RemovedBy" HeaderText="Removed By" />
<asp:BoundField DataField="RemovedDate" HeaderText="Date Removed" />
<asp:BoundField DataField="Description" HeaderText="Description" />
<asp:BoundField DataField="IsRemoved" Visible="false" />
</Columns>
</asp:GridView>
Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load
If (Page.IsPostBack) Then
Exit Sub
End If
gvTags.DataSource = GetTags()
gvTags.DataBind()
'NOTE - Here, DataSource has complete data (all rows & columns that should have data, do have data)
If (gvTags.Rows.Count > 0) Then
gvTags.HeaderRow.TableSection = TableRowSection.TableHeader
End If
End Sub
Protected Sub gvTags_RowDataBound(ByVal sender As Object, ByVal e As GridViewRowEventArgs)
If (Not e.Row.RowType = DataControlRowType.DataRow) Then
Exit Sub
End If
e.Row.FindControl("btnRemove").Visible = Not Boolean.Parse(DataBinder.Eval(e.Row.DataItem, "IsRemoved").ToString)
e.Row.FindControl("btnReapply").Visible = Boolean.Parse(DataBinder.Eval(e.Row.DataItem, "IsRemoved").ToString)
'NOTE - Here, gvTags.Columns(columnIndex) is null for each of the below three columns (RemovedBy, RemovedDate, and Description)
gvTags.Columns(removedByColumnIndex).Visible = checkbox.Checked
gvTags.Columns(removedDateColumnIndex).Visible = checkbox.Checked
gvTags.Columns(descriptionColumnIndex).Visible = (Not checkbox.Checked)
End Sub
My suggestion: if you columns are to be shown/hidden depending on a CheckBox outside of the grid, you could do this in the markup:
<asp:CheckBox ID="chkBox" runat="server" AutoPostBack="true" ... />
And process the event in code-behind:
Private Sub chkBox_CheckedChanged(sender As Object, e As System.EventArgs) Handles chkBox.CheckedChanged
gvTags.Columns(removedByColumnIndex).Visible = chkBox.Checked
gvTags.Columns(removedDateColumnIndex).Visible = chkBox.Checked
gvTags.Columns(descriptionColumnIndex).Visible = (Not chkBox.Checked)
gvTags.DataSource = GetTags()
gvTags.DataBind()
End Sub
Related
so I have a gridview which is displaying a db table I have.
I dont create the table manually obviously as this is what <%#Eval("text")%>' and Bind() do.
I created a unique table with my sql query to add two rows of sum in the bottom of the table, ( 2 last records), my question is:
is there a way in which I can access those rows to style them?
I think its not possible but still Im asking maybe Ill find out that theres a way.
thanks
Yes, the need to style a individual cell (auto generated columns, or bound columns), or even style the whole row.
Let's do all 3
First up, style a "cell" (these are in the cells collection, and autogenerated columns, and NON templated columns).
So, say this simple grid
<asp:GridView ID="GridView1" runat="server" Width="40%"
AutoGenerateColumns="False" DataKeyNames="ID" CssClass="table table-hover">
<Columns>
<asp:BoundField DataField="FirstName" HeaderText="FirstName" />
<asp:BoundField DataField="LastName" HeaderText="LastName" />
<asp:BoundField DataField="HotelName" HeaderText="HotelName" />
<asp:BoundField DataField="City" HeaderText="City" />
<asp:TemplateField HeaderText="Description">
<ItemTemplate>
<asp:Label ID="lblDescript" runat="server"
Text='<%# Eval("Description") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Active" ItemStyle-HorizontalAlign="Center">
<ItemTemplate>
<asp:CheckBox ID="chkActive" runat="server"
Checked='<%# Eval("Active") %>' />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
(note how I included BOTH templated columns which have plain jane asp.net controls like label, textbox etc., or the built in GV columns (data bound ones, or auto generated)
Code to load the GV is this:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
LoadData()
End If
End Sub
Sub LoadData()
Dim strSQL = "SELECT * FROM tblHotelsA ORDER BY HotelName"
Using conn As New SqlConnection(My.Settings.TEST4)
Using cmdSQL As New SqlCommand(strSQL, conn)
conn.Open()
Dim rst As New DataTable
rst.Load(cmdSQL.ExecuteReader)
GridView1.DataSource = rst
GridView1.DataBind()
End Using
End Using
End Sub
And we now have this:
Ok, so let's do example 1 - lets color the "city" Colum in above. Note how "city" is a "bound field".
So, auto generated, or bound fields = cells collection.
So, for things like conditional formatting, even combine some columns, change color, hide show images, or whatever?
you use the GV row databound event. (and this applies well to listview, repeaters, etc.)
So, lets say for city = Edmonton, we want a light blue cell, and for city = "Edmonton", we want some light green.
So, we use the row bound event.
This code:
Protected Sub GridView1_RowDataBound(sender As Object, e As GridViewRowEventArgs)
If e.Row.RowType = DataControlRowType.DataRow Then
Select Case e.Row.Cells(3).Text
Case "Edmonton"
e.Row.Cells(3).BackColor = System.Drawing.Color.SkyBlue
Case "Banff"
e.Row.Cells(3).BackColor = System.Drawing.Color.LightGreen
End Select
End If
End Sub
And we now have this:
However, the above for "templated" colums works a bit different.
Lets say we want to highligh the description when check box = true (checked).
In that case, we can't (don't) use the cells colleciton, but for templated controls, we use find control.
Like this:
Dim cActive As CheckBox = e.Row.FindControl("chkActive")
If cActive.Checked Then
Dim lblDes As Label = e.Row.FindControl("lblDescript")
lblDes.Font.Italic = True
e.Row.Cells(4).BackColor = System.Drawing.Color.LightGray
End If
NOTE how we EVEN set the font to italic in the label control.
And now we see this:
NOTE VERY close how we use findcontrol to get those templated controls.
Last but not least - bonus:
let's highlight the whole row for active, and NOT EVEN have the check box column in the GV (but it is in the database source).
So, say this markup for the columns:
<Columns>
<asp:BoundField DataField="FirstName" HeaderText="FirstName" />
<asp:BoundField DataField="LastName" HeaderText="LastName" />
<asp:BoundField DataField="HotelName" HeaderText="HotelName" />
<asp:BoundField DataField="City" HeaderText="City" />
<asp:TemplateField HeaderText="Description">
<ItemTemplate>
<asp:Label ID="lblDescript" runat="server"
Text='<%# Eval("Description") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
So, "active" check box is NOT EVEN displayed in the GV, (but, it is in the data source that feeds the gv).
So, we can do this:
Protected Sub GridView1_RowDataBound(sender As Object, e As GridViewRowEventArgs)
If e.Row.RowType = DataControlRowType.DataRow Then
Dim gData As DataRowView = e.Row.DataItem ' Grid data - NOT the GV row!!!!!!
If gData.Item("Active") = True Then
e.Row.Style.Add("Background-color", "LightGray") ' highlight whole row.
End If
End If
End Sub
And we now get this:
Just keep in mind that the "dataitem" (the full database row) is ONLY avaiable during the row data bind, and it WILL/DOES go out of scope once data binding is complete.
so basically using pretty much similar logics as albert's reply, I ended up catching two last rows manually and changing their colors.
protected void grdReports_PreRender(object sender, EventArgs e)
{
//finding 2 last rows, changing backcolor to the sum specified color '#5D7B9D' and the forecolor to white
//first table ( annual )
GridViewRow lastRow = grdReports.Rows[grdReports.Rows.Count - 1];
lastRow.BackColor = System.Drawing.Color.FromName("#5D7B9D");
lastRow.ForeColor = Color.White;
GridViewRow secondToLastRow = grdReports.Rows[grdReports.Rows.Count - 2];
secondToLastRow.BackColor = System.Drawing.Color.FromName("#5D7B9D");
secondToLastRow.ForeColor = Color.White;
//second table ( requested )
GridViewRow lastRowSecond = grdReports2.Rows[grdReports2.Rows.Count - 1];
lastRowSecond.BackColor = System.Drawing.Color.FromName("#5D7B9D");
lastRowSecond.ForeColor = Color.White;
GridViewRow secondToLastRowSecond = grdReports2.Rows[grdReports2.Rows.Count - 2];
secondToLastRowSecond.BackColor = System.Drawing.Color.FromName("#5D7B9D");
secondToLastRowSecond.ForeColor = Color.White;
}
I have an ASPX page that includes a GridView. I want to be able to select a row from the grid, and populate another section of the page based on the selected row. It works if I have EnableEventValidation="false" in the <%# Page %> line, but I have been told that I cannot use that because of a security concern. When I don't include it, selecting a grid row throws an "Invalid postback or callback argument" exception.
How can I implement row selection without disabling event validation?
Here is my code:
ASPX page:
<asp:GridView runat="server" ID="TheGrid" AutoGenerateColumns="false" DataKeyNames="id" EmptyDataText="No Data Found" AllowSorting="true">
<Columns>
<asp:BoundField DataField="FirstName" HeaderText="First Name" ReadOnly="true" SortExpression="FirstName" />
<asp:BoundField DataField="LastName" HeaderText="Last Name" ReadOnly="true" SortExpression="LastName" />
<asp:BoundField DataField="Email" HeaderText="Email" ReadOnly="true" SortExpression="Email" />
</Columns>
</asp:GridView>
ASPX.VB code:
Protected Sub TheGrid_RowDataBound(sender As Object, e As GridViewRowEventArgs) Handles TheGrid.RowDataBound
If e.Row.RowType = DataControlRowType.DataRow Then
e.Row.Attributes("onclick") = Page.ClientScript.GetPostBackClientHyperlink(TheGrid, "Select$" & e.Row.RowIndex)
e.Row.Attributes("style") = "cursor:pointer"
End If
End Sub
Protected Overrides Sub Render(writer As HtmlTextWriter)
ClientScript.RegisterForEventValidation("TheGrid")
MyBase.Render(writer)
End Sub
Note that when I select a row, the exception is thrown somewhere between Page_Load and Render.
Ok, lets wire up the GV two ways.
First way, drop in a plane jane button for the row click
(we will delete the button and add row click in 2nd example).
so, say this simple GV
<div id="MyGridArea" runat="server" clientidmode="static">
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
DataKeyNames="ID"
CssClass="table table-hover" Width="60em" GridLines="None"
ShowHeaderWhenEmpty="true">
<Columns>
<asp:BoundField DataField="FirstName" HeaderText="FirstName" />
<asp:BoundField DataField="LastName" HeaderText="LastName" />
<asp:BoundField DataField="City" HeaderText="City" />
<asp:BoundField DataField="HotelName" HeaderText="HotelName" />
<asp:BoundField DataField="Description" HeaderText="Description" />
<asp:TemplateField>
<ItemTemplate>
<asp:Button ID="cmdEdit" runat="server" Text="Edit" CssClass="btn myshadow"
OnClick="cmdEdit_Click" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</div>
Note how we just dropped in a plane jane button.
And our code to fill out above is 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 strSQL = "SELECT * FROM tblHotelsA ORDER BY HotelName"
GridView1.DataSource = Myrst(strSQL)
GridView1.DataBind()
End Sub
And now we have this:
Ok, so next part is to drop in a "div" area that allows edit of one row.
So, again, quite much plan jane controls.
And we can "hide" grid when we edit, and show edit area div.
But, I often use jQuery.UI. Really amounts to much the same code as simple hide/show, but this way jQuery.UI turns that SAME div into a nice pop up area.
So, that div area might look like this:
<div id="EditRecord" runat="server" style="float: left; display: none" clientidmode="Static">
<br />
<div style="float: left" class="iForm">
<label>HotelName</label>
<asp:TextBox ID="txtHotel" runat="server" f="HotelName" Width="280">
</asp:TextBox>
<br />
<label>First Name</label>
<asp:TextBox ID="tFN" runat="server" f="FirstName" Width="140"></asp:TextBox>
<br />
<label>Last Name</label>
<asp:TextBox ID="tLN" runat="server" f="LastName" Width="140"></asp:TextBox>
<br />
<label>City</label>
<asp:TextBox ID="tCity" runat="server" f="City" Width="140"></asp:TextBox>
<br />
<label>Province</label><asp:TextBox ID="tProvince" runat="server" f="Province" Width="75"></asp:TextBox>
</div>
etc. etc. etc.
so, now lets wire up the button above.
The button will simple:
Get current grid row
Get PK id
Load up div and display.
So, that code is this:
Protected Sub cmdEdit_Click(sender As Object, e As EventArgs)
Dim btn As Button = sender
Dim gRow As GridViewRow = btn.NamingContainer
EditRow(gRow.RowIndex)
End Sub
Sub EditRow(rowNum As Integer)
Dim intPK As Integer = GridView1.DataKeys(rowNum).Item("ID")
Dim strSQL As String = "SELECT * FROM tblHotelsA WHERE ID = " & intPK
Dim rstData As DataTable = Myrst(strSQL)
' load up our edit div
fLoader(Me.EditRecord, rstData.Rows(0))
ViewState("PK") = intPK
ScriptManager.RegisterStartupScript(Me.Page, Page.GetType, "mypopedit", "popedit()", True)
End Sub
As noted, I added a popup from jQuery.UI, but we could just use plain jane "div" and hide/show the grid and show the edit area (or like you have, have that edit area in full view).
(fLoader is a routine I built some time ago - I like everyone became VERY tired of typing code over and over to fill out text boxes etc., so for any text box etc., I use a "made up" attribute called f="Data base column name", and that routine just loops the controls on the form and fills them out. No different than hand coding simple assignments to controls, but with this code I can re-use it over and over.
So, we now see, get this:
Ok, so the only next goal is to add a row click
(and not use that edit button).
So, then all we need is a routine that will get the current row index, and call our edit row routine we have above.
So, we use row data bound, and add that click event that way.
but, do note how the above button click gets the current row. That nice short code works for repeaters, listview etc. (we used naming container).
But, if you want a row click in place of that button?
Then on row data bound, add this code:
Protected Sub GridView1_RowDataBound(sender As Object, e As GridViewRowEventArgs) Handles GridView1.RowDataBound
If e.Row.RowType = DataControlRowType.DataRow Then
e.Row.Attributes.Add("onclick",
"__doPostBack('myrowedit'," & e.Row.RowIndex & ")")
End If
End Sub
And in our page load event, we have this:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
LoadGrid()
Else
If Request("__EVENTTARGET") = "myrowedit" Then
EditRow(Request("__EVENTARGUMENT"))
End If
End If
End Sub
And a handy dandy routine that returns a table based on SQL I used above was this:
Public Function Myrst(strSQL As String) As DataTable
Dim rstData As New DataTable
Using mycon As New SqlConnection(My.Settings.TEST4)
Using cmdSQL As New SqlCommand(strSQL, mycon)
mycon.Open()
rstData.Load(cmdSQL.ExecuteReader)
End Using
End Using
Return rstData
End Function
So, all in all, not a lot of code.
You can try the above working example here:
http://www.kallal.ca/Website11/WebForm2
I have a drop down list 'Country', 'city' text box and an 'Add' button. The country drop down is NOT mandatory so I can just add a city without a country, adding an empty 'country' to the gridview works OK. the problem when I click on 'Edit' in the gridview it binds it to the first country in the list it does not just show a blank:
<asp:DropDownList ID="DDLCountry" runat="server" AutoPostBack="true" AppendDataBoundItems="true" OnSelectedIndexChanged="DDLCountry_SelectedIndexChanged" InitialValue="">
<asp:ListItem Text="------------------------ Select ------------------------" Value="" />
</asp:DropDownList>
<asp:TextBox ID="txtCity" runat="server"></asp:TextBox>
<asp:Button ID="btnNewLList" runat="server" OnClick="btnNewLList_Click" Text="Add new Country"/>
<asp:GridView ID="gvAddNewCountry" runat="server" AutoGenerateColumns="False" DataKeyNames="ID" OnRowCommand="gvAddNewCountry_RowCommand" OnRowDeleting="gvAddNewCountry_RowDeleting" OnRowDataBound="gvAddNewCountry_RowDataBound" OnRowUpdating="gvAddNewCountry_RowUpdating" OnRowEditing="gvAddNewCountry_RowEditing" OnRowCancelingEdit="gvAddNewCountry_RowCancelingEdit" ShowHeaderWhenEmpty="True">
<EmptyDataTemplate>
No Data
</EmptyDataTemplate>
<Columns>
<asp:TemplateField HeaderText="Actions">
<ItemTemplate>
<asp:Button ID="btnEdit" runat="server" Text="Edit"/>
</ItemTemplate>
</asp:TemplateField>
<asp:CommandField ButtonType="Button" ShowEditButton="true" ShowCancelButton="true">
</asp:CommandField>
<asp:TemplateField HeaderText="Country>
<ItemTemplate>
<asp:Label ID="lblCountry" runat="server" Text='<% #Eval("Country") %>'></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:DropDownList ID="DDCountry" runat="server" AppendDataBoundItems="True" AutoPostBack="false"></asp:DropDownList>
</EditItemTemplate>
</asp:TemplateField>
Code behind:
Protected Sub gvAddNewCountry_RowCommand(sender As Object, e As GridViewCommandEventArgs)
If e.CommandName = "Edit" Then
Dim rowCountryToEdit As Integer = e.CommandArgument
Dim ddListCountry As DropDownList = (CType(gvAddNewCountry.Rows(CInt(e.CommandArgument)).FindControl("DDCountry"), DropDownList))
ddListCountry.DataSource = (From x In Country Where x.Domain = "lCountry" Order By x.Description Select x).ToList()
ddListCountry.DataTextField = "Description"
ddListCountry.DataValueField = "ID"
ddListCountry.DataBind()
End If
End Sub
Thanks for your help X
Ok, so when you have/want a ddl in a gv row?
We require TWO steps.
First step: Load up the list of choices for the dll
2nd step: set the ddl to the current row value, or blank (no choice) if null no value exists yet for the current row. This ALSO means we have to get/grab the current row value for the dll, and set the ddl to reflect this existing choice.
So, this is a two step process.
And the "event" we typical use for this is the row bind event. (all such controls from listview, gridview and more have this event).
Also, a VERY nice helper tip? During (but ONLY during) the data bind event, you have FULL USE of ALL columns from the data source - EVEN COLUMNS NOT in the gv!!!
I don't have a entity database first setup that you have, but lets load up a gv with a combo box:
So, our gv:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
CssClass="table table-hover" Width="50%"
DataKeyNames="ID">
<Columns>
<asp:BoundField DataField="FirstName" HeaderText="First Name" />
<asp:BoundField DataField="LastName" HeaderText="First Name" />
<asp:BoundField DataField="HotelName" HeaderText="Hotel Name" />
<asp:BoundField DataField="City" HeaderText="City" />
<asp:BoundField DataField="Description" HeaderText="Descripiton" />
<asp:TemplateField HeaderText="Rating">
<ItemTemplate>
<asp:DropDownList ID="cboRating" runat="server"
DataTextField="Rating"
DataValueField="ID">
</asp:DropDownList>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
And our code to fill is this:
Dim rstRating As New DataTable
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()
' get data for rating combo
rstRating = MyRst("SELECT ID, Rating FROM tblRating ORDER BY ID")
' get data for grid
GridView1.DataSource = MyRst("SELECT * FROM tblHotelsA ORDER BY HotelName")
GridView1.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)
End Using
End Using
Return rstData
End Function
Note VERY carefull in above, I created a page wide (class wide) data table called rstRating. This will go out of scope after the data bind, but we ONLY need it to persit DURING the gv data bind operating (since for each row of the gv, we don't want to run that query over and over - we need this same pick list for the dll).
Ok, so now we see/get this:
The only part we need is to load up the dll, and set it for each row. We use the RowDataBound event.
So, code for that was this:
Protected Sub GridView1_RowDataBound(sender As Object, e As GridViewRowEventArgs) Handles GridView1.RowDataBound
' bind drop down for each row
If e.Row.RowType = DataControlRowType.DataRow Then
' get combo
Dim rDrop As DropDownList = e.Row.FindControl("cboRating")
rDrop.DataSource = rstRating
rDrop.DataBind()
rDrop.Items.Insert(0, New ListItem("Please Select", "0"))
' now get current row value for rating.
Dim gData As DataRowView = e.Row.DataItem
If IsDBNull(gData("Rating")) = False Then
rDrop.Text = gData("Rating")
End If
End If
End Sub
So, for each row, get the dll.
For for that row, load up with choices
And THEN for that row, set the ddl to the current row value (but check for null, and don't set - it will then show our "select" choice value.
I am new with .net!
I have two gridviews connected to a large database. The first one is returning a list of issues searched by ID while the other is returning the issues searched by subject.
I am trying to get the ID from the gridview returning issues from a select button but when I use selectedRow it doesn't return anything.
I tried multiple methods and this is what I have now. Any Suggestions?
Protected Sub IssuesGV_SelectedIndexChanging(ByVal sender As Object, ByVal e As GridViewSelectEventArgs)
Dim pName As String
pName = IssuesGV.SelectedRow.Cells(0).Text
BindGridComments(pName)
End Sub
Protected Sub IssuesGV_RowDataBound(ByVal sender As Object, ByVal e As GridViewRowEventArgs)
If e.Row.RowType = DataControlRowType.DataRow Then
e.Row.Attributes("onmouseover") = "this.style.backgroundColor='aquamarine';"
e.Row.Attributes("onmouseout") = "this.style.backgroundColor='white';"
e.Row.ToolTip = "Click last column for selecting this row."
' e.Row.Cells(0).Attributes.Add("onclick", )
End If
End Sub
Protected Sub IssuesGV_RowCommand(sender As Object, e As GridViewCommandEventArgs)
' ' Dim row As GridViewRow = IssuesGV.Rows(rowIndex)
' v = row.Cells(1).Text
'v = IssuesGV.SelectedRow.Cells(0).Text
' TextBox1.Text = v
'TextBox1.Text = v
If (e.CommandName = "Select1") Then
Dim index As Int16
index = Convert.ToInt32(e.CommandArgument)
Dim row As GridViewRow
row = IssuesGV.Rows(index)
Dim item As ListItem
item.Text = Server.HtmlDecode(row.Cells(0).Text)
End If
End Sub
My gridview code is the following (the one where I am using the select button):
<asp:GridView ID="IssuesGV" runat="server" AutoPostBack="true" OnRowCommand ="IssuesGV_RowCommand" OnRowDataBound="IssuesGV_RowDataBound" OnSelectedIndexChanged = "IssuesGV_OnSelectedIndexChanged" SelectedIndexChaning ="IssuesGV_SelectedIndexChanging" AutoGenerateColumns="False" DataKeyNames="number" DataSourceID="IssueDS" EnableModelValidation="True">
<Columns>
<asp:BoundField DataField="number" HeaderText="number" ReadOnly="True" SortExpression="number" />
<asp:BoundField DataField="subject" HeaderText="subject" SortExpression="subject" />
<asp:BoundField DataField="description" HeaderText="description" SortExpression="description" />
<asp:BoundField DataField="created_at" HeaderText="created_at" SortExpression="created_at" />
<asp:BoundField DataField="opener_name" HeaderText="opener_name" SortExpression="opener_name" />
<asp:BoundField DataField="project_name" HeaderText="project_name" SortExpression="project_name" />
<asp:ButtonField Text="Select" CommandName="Select1" ItemStyle-Width="30" ButtonType="Button" HeaderText="Select" ShowHeader="True" SortExpression="number" >
<ItemStyle Width="30px" />
</asp:ButtonField>
</Columns>
</asp:GridView>
The error I am receiving is this one:
System.ArgumentOutOfRangeException HResult=0x80131502
Message=Index was out of range. Must be non-negative and less than the
size of the collection. Parameter name: index Source= StackTrace:
Many Thanks!
Front End:
Your GridView should look like this:
<asp:GridView ID="IssuesGV" runat="server" AutoGenerateColumns="false"
OnSelectedIndexChanged="IssuesGV_OnSelectedIndexChanged">
<Columns>
<asp:BoundField DataField="number" HeaderText="number" />
...Some Other Fields
<asp:ButtonField Text="Select" CommandName="Select" ItemStyle-Width="150" />
</Columns>
</asp:GridView>
Back End:
Then add this code OnSelectedIndexChanged of GridView:
Protected Sub IssuesGV_OnSelectedIndexChanged(sender As Object, e As EventArgs)
'Accessing Selected BoundField Column
Dim number As String = IssuesGV.SelectedRow.Cells(0).Text
label.Text = "<b>Number Value:</b> " & number & " <b>"
End Sub
Ref: See full example here.
Edit
For some reason, if OnSelectedIndexChanged method is not firing then you've just need to add below attribute in your GridView header markup:
AutoGenerateSelectButton="True"
This will create a Select link in your GridView rows, which'll fire the OnSelectedIndexChanged method.
PS: If above all workarounds not works then see this post.
I have a GridView where I want to hide some of the rows when the price is 0. When I try to check the value I get a blank string for all rows.
Markup: non relevant rows have been removed for readability. getProductInfo and getPrice are lookup functions receiving and returning strings
<asp:GridView ID="gvRebuild" runat="server" AutoGenerateColumns="false" Width="100%" OnRowDataBound="gvRebuild_RowDataBound">
<Columns>
<asp:BoundField ... />
<asp:TemplateField ... />
</asp:TemplateField>
<asp:TemplateField HeaderText="Price" ItemStyle-Width="12%">
<ItemTemplate>
<asp:Label runat="server" ID="price" ><%# getPrice(getProductInfo(Eval("fieldName")))%></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField ... />
</Columns>
</asp:GridView>
Code Behind:
Protected Sub gvRebuild_RowDataBound(sender As Object, e As GridViewRowEventArgs)
Dim p As Label = e.Row.FindControl("price")
If p IsNot Nothing Then
Debug.Print(String.Format("*{0}*", p.Text))
If p.Text = "$0.00" Then
e.Row.Visible = False
End If
End If
End Sub
The debug statement is confirming that all values found in the "price" control are blank. I have also confirmed via debugger that the getPrice function is returning the correct value and firing before the RowDataBound event handler for each row.
You have to check the RowType. The first row will be the header row. The header row does not contain the TextBox, hence the NULL error.
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
//use findcontrol here
}
}
VB
Protected Sub GridView1_RowDataBound(ByVal sender As Object, ByVal e As GridViewRowEventArgs)
If (e.Row.RowType = DataControlRowType.DataRow) Then
'use findcontrol here
End If
End Sub
Update
I see what you mean now. It is the value that is NULL not the control itself.
I did some testing and it turns out that if you use your method it does not work. But change it to this and it will.
<asp:Label runat="server" ID="price" Text='<%# getPrice(getProductInfo(Eval("fieldName"))) %>'></asp:Label>
It seems that the binding of data inside the tag is done after the row or gridview has completed, but the Text property is set right away.