Friday, February 17, 2012

DataKey and DataKeyNames in a Gridview

Hack The Gibson

What good are these parameters?  Well let’s take a concept of a GridView that displays a list of files we have stored in our SQL Database.  So basically, we have a document repository and it is displayed as so:

File Number File Name Size Date
1 anything.txt 489kb 01/01/1900
2 everything.txt 572kb 02/02/1902
       

This being the case, we want it so that if we click on a column (for simplicity we will use File Number, but in fact you could even use the entire row), it will trigger an event and then go to the database, lookup the detail information, and display it in a separate Panel/Page or other form of display.

The idea behind the DataKey and DataKeyNames properties is to identify to the system exactly which record (or row) that the user clicked on. 
The DataKeyNames property is made up of a single or multiple value list of fields that help identify a unique record.  So in our example above, we could use File Number or File Name or to make sure we get an exact unique match, we could use both.
DataKeyNames are made up of String Arrays.  As such, they are comma delimited.  So to properly code the GridView it would look like:

DataKeyNames="File Number, File Name"




This being the case, we would correctly construct a GridView like so:





<asp:GridView ID="gdvDocuments" runat="server" AllowPaging="False" AutoGenerateColumns="false"



                DataKeyNames="file number, file name" enableviewstate="false"



                EmptyDataText="There are no documents for this issue." AllowSorting="false"  



                ShowHeader="True" CssClass="GridTable" GridLines="None"  >



            <EmptyDataRowStyle CssClass="NoRows" />



            <FooterStyle CssClass="GridFooter" />



            <PagerStyle CssClass="GridPaging" />            



            <HeaderStyle ForeColor="White" />



            <Columns>              



                <asp:ButtonField DataTextField="file number" HeaderText="File Number" ButtonType="Link" CommandName="btnFileNumber" />



                <asp:ButtonField DataTextField="file name" HeaderText="File Name" ButtonType="Link" CommandName="btnFileName" />



                <asp:BoundField DataField="size" HeaderText="Size" />



                <asp:BoundField DataField="uploadDate" HeaderText="Upload Date" />



            </Columns>



        </asp:GridView>




The power in the GridView comes from the CommandName argument from our ButtonFields.  This will tell us which button was pressed.  Also notice that I made the button type a link button (as in a hyperlink) as opposed to something like an image.

To help facilitate the event of clicking the button and the action associated with it, we will use the ROWCOMMAND event of the GridView like so:






Protected Sub gdvDocuments_RowCommand(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewCommandEventArgs) Handles gdvDocuments.RowCommand



        If e.CommandName = "btnDownload" Then



            Dim rowIndex As Integer = CInt(e.CommandArgument.ToString())



            rw_BLL.cusip = gdvDocuments.DataKeys(rowIndex).Values("cusip").ToString().Trim()



            rw_BLL.filename = gdvDocuments.DataKeys(rowIndex).Values("filename").ToString().Trim()



            rw_BLL.sendDocumentToUser()



            Response.ContentType = "application/pdf"



            Response.BinaryWrite(rw_BLL.content)



            Response.End()



        End If



        If e.CommandName = "btnDeleteFile" Then



            Dim rowIndex As Integer = CInt(e.CommandArgument.ToString())



            rw_BLL.cusip = gdvDocuments.DataKeys(rowIndex).Values("cusip").ToString().Trim()



            rw_BLL.filename = gdvDocuments.DataKeys(rowIndex).Values("filename").ToString().Trim()



            rw_BLL.deleteNewDocument()



            redirectPage()



        End If



    End Sub




Here you will see the code for both buttons listed under the RowCommand event for our GridView gdvDocuments.  Our first line tests to see which button was pressed using the commandname argument that we set in HTML on the aspx page.  e represents our command arguments (so relevant parameters for the row can be accessible by using the e variable).  Thus, e.CommandName represents the name of the button that we clicked.  If we really wanted to get created we would use an IF/ELSEIF/and ELSE with the final ELSE Exiting Sub and maybe setting a label to tell the user we couldn’t find the commandname they were looking for (just a bit of error checking).

However, If we follow the logic path, the next thing we need to know is what row did the user click our button on.  For that, we convert the command argument to an integer and name is rowIndex.



So now we get into our datakeys.  We reference our datakey beginning at the GridView (as DataKeys is a parameter of the GridView).  Then we tell it the rowIndex which was clicked on.  This is important because we want to make sure we want the key for the specific row where the document resides.  As apart of this we want the value “file name” or other important key field that we specified in the datakeys property of the GridView.  Of course we are extracting the value to string so that we can send it to SQL where we will use it in the WHERE clause.

Notice I do this several times which is what it took to uniquely identify a file. 
The rest of the code is used to send the three datakeys to SQL, get the file from the record and send it to the user (which I have discussed in prior blogs).


We repeat the same logic for the second button.



UPDATE: I have since realized that I used an example for a GridView that doesn’t match the code-behind.  The logic is the same you just have to match the datakeys you define in the GridView to the DataKeys(rowIndex).Values… in the code-behind.  I apologize for this oversight, a product of writing this article over several days.



Happy .Netting… Saleh



Hack the Gibson

No comments:

Post a Comment