Kindly help Index was out of range. Must be non-negative - asp.net

<asp:GridView ID="gvUnitNomRoll" runat="server" OnRowCommand ="gvUnitNomRoll_RowCommand1" SkinID="gridviewSkin" Width="100%"
DataKeyNames="id, name, desig, idr, service" EmptyDataText="" AutoGenerateColumns="false">
<Columns>
<asp:TemplateField HeaderText="Sl" HeaderStyle-HorizontalAlign="Center" ItemStyle-HorizontalAlign="Center">
<ItemTemplate> <%#Ctype (Container, GridViewRow).RowIndex+1 %></ItemTemplate>
</asp:TemplateField>
<asp:BoundField HeaderText="id" DataField="name" Visible ="false"/>
<asp:BoundField HeaderText="Name" DataField="name"/>
<asp:BoundField HeaderText="desig" DataField="desig" />
<asp:BoundField HeaderText="Idr" DataField="idr" />
<asp:BoundField HeaderText="Service" DataField="service" />
<asp:ButtonField ButtonType="Button" CommandName="ed" ControlStyle-CssClass ="allBtn blue" HeaderText="Update Details"
ItemStyle-HorizontalAlign="Center" ItemStyle-Width="80px" Text="Update" />
<asp:ButtonField ButtonType="Button" CommandName="tfrOut" ControlStyle-CssClass ="allBtn red"
HeaderText="Transfer" ItemStyle-HorizontalAlign="Center" ItemStyle-Width="80px" Text="Transfer Out" />
<asp:ButtonField ButtonType="Button" CommandName="Verify" ControlStyle-CssClass ="allBtn green"
HeaderText="Verify" ItemStyle-HorizontalAlign="Center" ItemStyle-Width="80px" Text="Verify" />
</Columns>
</asp:GridView>
this is my vb.code
Dim CmdName As String = e.CommandName
Dim nInt As Integer = Convert.ToInt32(e.CommandArgument)
Dim currentPno As String = gvUnitNomRoll.DataKeys(nInt).Item("id").ToString() 'Here throws error '
If (e.CommandName = "ed") Then
If currentPno <> "" Then
It throws error
Index was out of range. Must be non-negative and less than the size of the collection. Parameter name: index
while debugging
Dim currentPno As String = gvUnitNomRoll.DataKeys(nInt).Item("id").ToString() 'Here throws error '

Lets back the truck here a bit.
first up, there is VERY little reason to stuff up datakeys with all those values. You HAVE those values in the grid, so, no real need to put them again into datakeys.
Datakeys as a genreal rule SHOULD ONLY hold the database primary key "ID".
And daykeys are nice, since THEN you don't have to display/include/have/worry about showing that ID in the GV. (users don't need to see or care). And in fact for security reasons, you don't need nor want to include the database PK id in that gv anyway. (kind of the whole point of datakeys).
Also, I don't see ANYWHERE where you are setting command arument, but you THEN attmept to pull command augrement into a int value (so, that's where your code is failing).
so, in general, if you want a simple button click in the GV?
Then just drop in a plain jane regular button. They work better, are easy to use, and BETTER you do DOUBT in the past worked with a plain jane good old asp.net button.
So, I don't have your data, but lets load up a gv with some rows of data (Hotels). then add a button click to the gv, and then get/enjoy/use/have use of the one data row the user clicked on.
<h3>Hotels</h3>
<asp:GridView ID="GridView1" runat="server" Width="40%"
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:BoundField DataField="City" HeaderText="City" />
<asp:BoundField DataField="Description" HeaderText="Description" />
<asp:TemplateField>
<ItemTemplate>
<asp:Button ID="cmdEdit" runat="server" Text="Edit"
CssClass="btn"
onclick="cmdEdit_Click" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
So, use a "Template" field, and inside of that, you can put ANY standard plane jane asp.net control - including that of a button.
Now, in most cases, when we drag + drop a button into a webform, we can double click on that button to wire up a click event. However, since the button is "nested" inside of the gv, then we can't easy double click on the button, and jump to the code behind stub.
So, in markup view, simple type in onclick=.
When you hit "=", then intel-sense will kick in, and "offer" you to create the simple button click.
it works, looks like this:
so, here is a our gv markup:
<h3>Hotels</h3>
<asp:GridView ID="GridView1" runat="server" Width="40%"
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:BoundField DataField="City" HeaderText="City" />
<asp:BoundField DataField="Description" HeaderText="Description" />
<asp:TemplateField>
<ItemTemplate>
<asp:Button ID="cmdEdit" runat="server" Text="Edit"
CssClass="btn"
OnClick="cmdEdit_Click"
/>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
And our code behind 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"
Dim cmdSQL As New SqlCommand(strSQL)
GridView1.DataSource = MyrstP(cmdSQL)
GridView1.DataBind()
End Sub
Ok, so now we need the event code for that button click.
Protected Sub cmdEdit_Click(sender As Object, e As EventArgs)
Dim btn As Button = sender
Dim gRow As GridViewRow = btn.NamingContainer
Dim intPK As Integer = GridView1.DataKeys(gRow.RowIndex).Item("ID")
Dim cmdSQL = New SqlCommand("SELECT * FROM tblHotelsA WHERE ID = #ID")
cmdSQL.Parameters.Add("#ID", SqlDbType.Int).Value = intPK
Dim rstHotel As DataTable = MyrstP(cmdSQL)
Debug.Print($"Row click = {gRow.RowIndex}")
Debug.Print($"Data base PK id (data keys) = {intPK}")
Debug.Print($"Hotel Name from gv = {gRow.Cells(2).Text}")
If rstHotel.Rows.Count > 0 Then
Call EditOne(rstHotel.Rows(0))
End If
End Sub
So, output from above is this:
And clicking on a row button, we get this:
output:
Row click = 5
Data base PK id (data keys) = 3
Hotel Name from gv = Sandman Inn
Of course I have a routine called "Editone". All that does is hide the GV, display a div with standard controls, and some code that fills out the controls.
So, edit one looks like:
Sub EditOne(MyRow As DataRow)
ViewState("PKID") = MyRow("ID")
fLoader(EditRecord, MyRow)
GridView1.Visible = False
EditRecord.Visible = True
End Sub
so, now we see/get this:
"fLoader" is a routine that loops all controls in that div, and shoves in values from the one data row.

Related

How to dynamically assign ID to a checkbox in a for-each cycle

I have the following code in a ascx : I run a SQL query and I put it in a Datatable. Then I show the values in the page like this
<% For each row As DataRow In myDataTable.Rows %>
<%=row("something") %>
<%=row("somethingelse") %>
<asp:CheckBox ID="CheckBox1" runat="server" />
<% next %>
Now... how can I set the ID of the checkbox dynamically?
something like
<asp:CheckBox ID="<%=row("MyId")%>" runat="server" />
that obviously do not work.
I need to set the id as the value I get from the DB so if it is checked I can pass the checked id to another page.
The problem is that row("MyId") returns type of object so you need to convert it to string to be able to bind it to Checkbox
<asp:CheckBox ID="<%=row('MyId').ToString()%>" runat="server" />
See: DataRow.Item[] Property
Hum, would not a data control say like listview, or gridview be better here?
You can have this markup:
<asp:GridView ID="GVHotels" runat="server" class="table" AutoGenerateColumns="false">
<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" HeaderStyle-Width="200" />
<asp:BoundField DataField="Description" HeaderText="Description" />
<asp:TemplateField HeaderText="Active" ItemStyle-HorizontalAlign="Center" >
<ItemTemplate>
<asp:CheckBox ID="ckActive" runat="server"
Checked=<%# Eval("Active") %> />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Now to load we have this:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
Dim strSQL As String =
"SELECT TOP 10 FirstName, LastName, HotelName, City, Description, Active
FROM tblHotels WHERE description is not null ORDER BY HotelName"
GVHotels.DataSource = MyRst(strSQL)
GVHotels.DataBind()
End If
End Sub
and we get this:
So, it is a lot less work to do the above.
Even if you don't have a bound check box, you can even feed the grid the data, and display a un-bound check box for selecting rows if that what you need/want.

Is it possible to change grid color in asp.net using particular column value from database

I have one particular column value in the database, which has different values, As I want to change the color of grid in asp.net, based on each value. I don't want to hard code the column value
Thanks in Advance
Ok, assume a table like this:
Ok, so that is a table. I suppose the column could be in the same as our table that drives the grid view, but the process works the same.
Ok, so now our markup:
<asp:GridView ID="GridView1" 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:BoundField DataField="City" HeaderText="City" />
<asp:BoundField DataField="Province" HeaderText="Province" />
<asp:BoundField DataField="Description" HeaderText="Description" />
</Columns>
</asp:GridView>
And our code to load the grid:
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 As String =
"SELECT tblHotels.ID, FirstName, LastName, HotelName, tblHotels.City, Province, Description, Color from tblHotels
LEFT JOIN tblCityColor on tblCityColor.City = tblHotels.City
ORDER BY HotelName"
Using cmdSQL As SqlCommand = New SqlCommand(strSQL, New SqlConnection(My.Settings.TEST3))
cmdSQL.Connection.Open()
Dim rstTable As New DataTable
rstTable.Load(cmdSQL.ExecuteReader)
GridView1.DataSource = rstTable
GridView1.DataBind()
End Using
End Sub
The above loads our grid. But for formatting colors? We joined in that above "color" table into the query.
So, now in the row data bound event, we can do this:
Protected Sub GridView1_RowDataBound(sender As Object, e As GridViewRowEventArgs) Handles GridView1.RowDataBound
If e.Row.RowType = DataControlRowType.DataRow Then
Dim gData As DataRowView = e.Row.DataItem
If IsDBNull(gData.Item("Color")) = False Then
e.Row.Cells(3).BackColor = FromName(gData.Item("Color"))
e.Row.Cells(5).BackColor = FromName(gData.Item("Color"))
End If
End If
End Sub
Not that for defaulted gv columns, or databound, the columns appear in the cells array as per above.
Output:
Now it is possible you have some (or all) templated fields in the gv.
You then don't use cells collection, but have to use find control.
So say our grid has this markup:
<asp:GridView ID="GridView1" 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:BoundField DataField="City" HeaderText="City" />
<asp:BoundField DataField="Province" HeaderText="Province" />
<asp:TemplateField HeaderText="Description">
<ItemTemplate>
<asp:TextBox ID="txtDescript" runat="server"
Text = '<%# Eval("Description") %>' >
</asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
So for above, to change the description (which is a plane jane text box). then the code to format background color would be:
If e.Row.RowType = DataControlRowType.DataRow Then
Dim gData As DataRowView = e.Row.DataItem
If IsDBNull(gData.Item("Color")) = False Then
e.Row.Cells(3).BackColor = FromName(gData.Item("Color"))
Dim txtDesc As TextBox = e.Row.FindControl("txtDescript")
txtDesc.BackColor = FromName(gData.Item("Color"))
End If
End If

Show/hide column in gridview based on Role

I have a GridView I populate, and want to show/hide the edit link based on whether the person logged in is either an Admin or User. I am not receiving any errors but cannot figure out why its not working.
aspx
<asp:GridView ID="RepView" runat="server" HeaderStyle-BackColor="#bfbfbf" HeaderStyle-ForeColor="White" HeaderStyle-Font-Underline="true" CellPadding="2" GridLines="None" AutoGenerateColumns="false" Width="990px">
<AlternatingRowStyle BackColor="#DCDCDC" />
<Columns>
<asp:BoundField DataField="Id" HeaderText="Id" />
<asp:BoundField DataField="FirstName" HeaderText="First Name" />
<asp:BoundField DataField="LastName" HeaderText="Last Name" />
<asp:BoundField DataField="EmployeeId" HeaderText="Employee Id" />
<asp:BoundField DataField="Shift" HeaderText="Shift" />
<asp:BoundField DataField="Supervisor" HeaderText="Supervisor" />
<asp:BoundField DataField="Center" HeaderText="Center" />
<asp:BoundField DataField="DateSubmitted" HeaderText="Date Entered" />
<asp:TemplateField ItemStyle-HorizontalAlign="Center" HeaderText="Details">
<ItemTemplate>
Edit
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
code behind
Private Sub BindGrid()
Dim DefaultConnection As String = ConfigurationManager.ConnectionStrings("DefaultConnection").ConnectionString
Using con As New SqlConnection(DefaultConnection)
'This is not working...
If My.User.IsInRole("User") Then
RepView.Columns(9).Visible = False
ElseIf My.User.IsInRole("Admin") Then
RepView.Columns(9).Visible = True
End If
' End of questionable part....
Using cmd As New SqlCommand()
cmd.CommandText = ("SELECT * from Reps")
cmd.Connection = con
con.Open()
RepView.DataSource = cmd.ExecuteReader()
RepView.DataBind()
con.Close()
End Using
End Using
End Sub
Try moving your code behind "Questionable Part" from the Private Sub BindGrid() to The gridview_Load event. My guess is that what's happening is that the gridview is loading, then it gets to your code Private sub BindGrid() to show/hide columns but the columns are already loaded, therefor it can not hide them. It will continue to show the columns even after running through this code unless you run the check and show/hide the columns in the load event.
One other possible solution is that it looks like in the Private Sub BindGrid() you are trying to hide the columns before the query which means the columns will not have been created yet so you have to create the columns first before you can hide and of them. Move the questionable part down below your sql command.
Try something like this...
Protected Sub GridView1_RowDataBound(sender As Object, e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles GridView1.RowDataBound
Dim x As Integer = 0
If x = 0 Then
GridView1.Columns(0).Visible = False
Else
GridView1.Columns(0).Visible = True
End If
End Sub
I have tested this and using x = 0 will hide the first column using x = 1 will show the first column.
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
DataKeyNames="ID" DataSourceID="SqlDataSource1">
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
ConnectionString="<%$ ConnectionStrings:Sprayer_Parts_CatalogConnectionString %>"
SelectCommand="SELECT [ID], [Order#] AS column1, [Gallon], [Price] FROM [Tanks]">
</asp:SqlDataSource>

How do I retrieve data from a hidden column in GridView? VB

I'm kind of stuck here, after doing some research I can't seem to find an answer. Anyway I don't know how can I retrieve the Primary key in my Gridview hidden column.
Here is my gridview
<asp:GridView ID="grdDent" runat="server" AutoGenerateColumns="False" Width="852px" DataKeyNames="app_id">
<Columns>
<asp:TemplateField>
<EditItemTemplate>
<asp:CheckBox ID="chkApp" runat="server" />
</EditItemTemplate>
<ItemTemplate>
<asp:CheckBox ID="chkApp" runat="server" />
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="app_id" HeaderText="app_id" Visible="False" />
<asp:BoundField DataField="app_date" HeaderText="Date" SortExpression="Date" />
<asp:BoundField DataField="app_time" HeaderText="Time" SortExpression="Time" />
<asp:BoundField DataField="app_rsn" HeaderText="Reason" SortExpression="Reason" />
<asp:BoundField DataField="app_info" HeaderText="Comment" SortExpression="Comment" />
<asp:BoundField DataField="app_sts" HeaderText="Status" SortExpression="Status" />
<asp:BoundField DataField="Patient" HeaderText="Requested by" SortExpression="Patient" />
<asp:BoundField DataField="app_timestamp" HeaderText="Date requested" SortExpression="Date requested" />
</Columns>
</asp:GridView>
And here is my code at button click
For Each row As GridViewRow In grdDent.Rows
If row.RowType = DataControlRowType.DataRow Then
Dim chkApp As CheckBox = TryCast(row.Cells(0).FindControl("chkApp"), CheckBox)
If chkApp.Checked Then
cmd = New MySqlCommand("UPDATE appointment_table SET app_sts = 'Approved' WHERE app_id = #p1", con)
cmd.Parameters.AddWithValue("#p1", row.Cells(1).Text)
con.Open()
cmd.ExecuteNonQuery()
con.Close()
End If
End If
Next
Here is my code to fill up the gridview
Using cmd = New MySqlCommand("SELECT app_id, app_date, app_time, app_rsn, app_info, app_sts, group_concat(pat_lname, pat_fname) As Patient, app_timestamp FROM appointment_table INNER JOIN patient_table WHERE app_sts = 'Queue'", con)
con.Open()
Dim ds As New DataSet()
Dim a As New MySqlDataAdapter(cmd)
a.Fill(ds)
grdDent.DataSource = ds
grdDent.DataBind()
con.Close()
End Using
The problem now is that whenever I click the button, it would not do anything, not even show an error, so I do not know what to do.
First debug the code and check from which line you are getting the error.
Also try following code.
.HideData
{
display: none;
}
Replace your app_id bound field like as below.
Don't use visible false property.
when you set visible=false that column will not rendered in gridview's html.
so, instead of visible=false make its style='display:none'
use like this :
<asp:BoundField DataField="ItemDesc" HeaderText="app_id" >
<ItemStyle CssClass="hidden"/>
</asp:BoundField>
<style type="text/css">
.hidden
{
display:none;
}
</style>
and use this in your foreach loop
dim appid as string
appid=row.Cells(1).Text
I see that you store the primary key in DataKeyNames="app_id"
so you would grab that in code with
grdDent.DataKeys.Item(a row index here).Value
You can drop the BoundField holding this value. It being "Visible=False" will not hold any value.
The way I do it is like this..
1st remove your boundfield and just add a lable to one of the template fields like this.
<asp:GridView ID="grdDent" runat="server" AutoGenerateColumns="False" Width="852px" DataKeyNames="app_id">
<Columns>
<asp:TemplateField>
<EditItemTemplate>
<asp:CheckBox ID="chkApp" runat="server" />
</EditItemTemplate>
<ItemTemplate>
<asp:CheckBox ID="chkApp" runat="server" />
<asp:Label ID="lblApp_ID" Visible="False" runat="server" Text='<%# Bind("app_id") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="app_date" HeaderText="Date" SortExpression="Date" />
<asp:BoundField DataField="app_time" HeaderText="Time" SortExpression="Time" />
<asp:BoundField DataField="app_rsn" HeaderText="Reason" SortExpression="Reason" />
<asp:BoundField DataField="app_info" HeaderText="Comment" SortExpression="Comment" />
<asp:BoundField DataField="app_sts" HeaderText="Status" SortExpression="Status" />
<asp:BoundField DataField="Patient" HeaderText="Requested by" SortExpression="Patient" />
<asp:BoundField DataField="app_timestamp" HeaderText="Date requested" SortExpression="Date requested" />
</Columns>
</asp:GridView>
by doing this it will put the label in each row but it wont show up to the user and the part that says "Text='<%# Bind("app_id") %>'" that binds the text to that label in each row.
Now for the code on the button click you should use this:
Dim i As Integer = 0
Dim app_ID As Integer '<- I was using an integer but you can use any datatype
For Each row As GridViewRow In grdDent.Rows
If CType(row.FindControl("chkApp"), CheckBox).Checked = True Then
app_ID = CType(grdDent.Rows(i).FindControl("lblApp_ID"), Label).Text
cmd = New MySqlCommand("UPDATE appointment_table SET app_sts = 'Approved' WHERE app_id =" & app_ID , con)
con.Open()
cmd.ExecuteNonQuery()
con.Close()
End If
i += 1
Next
All of this has worked for me, so I hope it works for you!
You can use something like this:
For Each row As GridViewRow In yourgrid.Rows
Dim chk As CheckBox = CType(row.FindControl("chkApp"), CheckBox)
If chk IsNot Nothing And chk.Checked Then
'get your selected row data here and perform update operation
End If
Next row
NOTE: My suggestion is to first debug the code and make sure your code is working fine and method is calling perfectly.
You can check getting asp.net gridview selected row data from server-side to get more details.
Hope it helps you!

Get the value of one column in gridview based on what row is clicked by the user

I have this code and I can't get the value of student number based on what row is clicked by the user
ASPX
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false"
OnSelectedIndexChanged="SelectEvent_click" HorizontalAlign="Center" DataKeyNames="StudentNumber">
<Columns>
<asp:BoundField DataField="StudentNumber" HeaderText="Student Number"/>
<asp:BoundField DataField="F_name" HeaderText="First name"/>
<asp:BoundField DataField="L_name" HeaderText="Last name"/>
<asp:BoundField DataField="Course" HeaderText="Course"/>
<asp:BoundField DataField="Date" HeaderText="Date" DataFormatString="{0:dd-MMM-yyyy}"/>
<asp:TemplateField HeaderText="View Application">
<ItemTemplate>
<asp:LinkButton ID="lnkApplication" runat="server" onClick = "SelectEvent_click"
Text="Select"></asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
VB
Protected Sub SelectEvent_click(sender As Object, e As EventArgs) Handles GridView1.SelectedIndexChanged
Label1.Text = GridView1.SelectedValue
If GridView1.SelectedIndex >= 0 Then
Response.Write(Label1.Text)
Session("StudentNumber") = Label1.Text
Response.Redirect("PCOApplicationView.aspx")
Else
Response.Write("Something bad happen please try again later!!")
End If
End Sub
You can use NamingContainer property on button click event, somthing like this :
Dim btn As LinkButton = DirectCast(sender, LinkButton)
GridViewRow = DirectCast(btn.NamingContainer, GridViewRow)

Resources