<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 '
Let's back up 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 general 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 argument, but you THEN attempt to pull command argument into a int value (so, that's where your code is failing).
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 good old asp.net button.
I don't have your data, but let's load up a gv with some rows of data (Hotels). Then add a button click to the gv, and then get 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 plain 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.
In markup view, simple type in onclick=.
When you hit "=", then IntelliSense will kick in, and "offer" you to create the simple button click.
This works, and 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:
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.