Monday, June 28, 2010

How To Fill a GridView with Custom Objects in an Arraylist using a DataTable

Usually when I use a GridView, I pull and write to a database table, which is the easiest way to use them. All of the Edit and Delete commands are pretty much prepackaged together with the SqlDataSource control.

However, I recently found myself building a shopping cart tool that didn't touch a database until the user submits the order. I personally like to write to the database right away in case the client gets disconnected, but in this particular case, I didn't have that pleasure.

So, I needed to be able to pull an arraylist of objects of type ORDER (a custom class I build) out of the session variable SHOPPINGCART (another custom class I built) and feed them into a gridview for the user to edit quantity, remove items from the cart, etc before checking out.

I first put together my GridView:
<asp:GridView
ID="gvYourCart"
DataKeyNames="OrderID"
AutoGenerateColumns="false"
runat="server">
<Columns>
<asp:BoundField
HeaderText="Quantity"
DataField="Quantity" />
<asp:BoundField
HeaderText="Device Model"
DataField="Device Model"
ReadOnly="true" />
<asp:BoundField
HeaderText="Rate Plan"
DataField="Rate Plan"
ReadOnly="true" />
<asp:BoundField
HeaderText="Total One Time Cost"
DataField="Total One Time Cost"
ReadOnly="true" />
<asp:BoundField
HeaderText="Total Recurring Costs"
DataField="Total Recurring Costs"
ReadOnly="true" />
</Columns>
</asp:GridView>

I only want users to be able to edit the Quantity field and remove orders from the cart, so I've made all other columns readonly.

Now, to start populating my gridview, I'll need to create a DataTable and populate it with the fields that are relavant to what I'll be displaying.
Private _dt As Data.DataTable
Public Sub Form_Load() Handles Me.Load
CType(Master.FindControl("nav_order"), HtmlTableCell).Attributes.Add("class", "nav_highlight")
_dt = New Data.DataTable()
_dt.Columns.Add("OrderID")
_dt.Columns.Add("Quantity")
_dt.Columns.Add("Product Model")
_dt.Columns.Add("Total One Time Cost")
gvYourCart.DataSource = _dt
If Not IsPostBack Then
BindData()
End If
End Sub

Public Sub BindData()
For Each thisOrder As Order In CType(Session("ShoppingCart"), ShoppingCart).Orders
Dim newRow As Data.DataRow = _dt.NewRow()
newRow.Item("OrderID") = thisOrder.ID
newRow.Item("Quantity") = thisOrder.Quantity
newRow.Item("Product Model") = thisOrder.Product.Name
newRow.Item("Total One Time Cost") = FormatCurrency(thisOrder.OneTimeCost(), 2)
_dt.Rows.Add(newRow)
Next
gvYourCart.DataBind()
End Sub

Because I know that I will need to bind data to my gridview every time I edit or delete from the control, I went ahead and created a BindData function that will pull data from my Shopping Cart in sessions and tie its data to the DataTable.

In order to edit and delete rows of my GridView, I will need to create 4 new functions (these are usually handled by the UpdateCommand and DeleteCommand of the SqlDataSource, but we'll need to build our own since we're doing things a little more custom than usual.

Add the following tags to the GridView control:
AutoGenerateEditButton="true"
AutoGenerateDeleteButton="true"
OnRowEditing="EditQty"
OnRowCancelingEdit="CancelEditQty"
OnRowUpdating="UpdateEditQty"
OnRowDeleting="DeleteOrder"


Now, at this point your code may look nothing like mine, but this should give you a pretty good start.

The EditQty sub procedure will pretty much always look like this. All we are doing is telling the GridView which row we will be editing. Because we set some columns as ReadOnly, they will not be editable.

Public Sub EditQty(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewEditEventArgs)
gvYourCart.EditIndex = e.NewEditIndex
BindData()
End Sub


Again, the CancelEditQty sub procedure is pretty standard. We are just letting the gridview know that we don't want to edit any rows by setting the EditIndex to -1.

Public Sub CancelEditQty()
gvYourCart.EditIndex = -1
BindData()
End Sub


Because I didn't allow for sorting on my GridView, I know that the shopping cart's order are displayed on the GridView in the same order as they are stored in the shopping cart, so I can afford to make the assumption that the index of the ArrayList in my ShoppingCart object's Orders property matches the e.RowIndex of the GridView, but be careful of how you make your edits.

Public Sub UpdateEditQty(ByVal sender As Object, ByVal e As GridViewUpdateEventArgs)
Dim thisRow As GridViewRow = gvYourCart.Rows(e.RowIndex())
CType(CType(Session("ShoppingCart"), ShoppingCart).Orders(e.RowIndex), Order).Quantity = CType(thisRow.Cells(1).Controls(0), TextBox).Text

gvYourCart.EditIndex = -1
BindData()
End Sub

Ditto.

Public Sub DeleteOrder(ByVal sender As Object, ByVal e As GridViewDeleteEventArgs)
CType(Session("ShoppingCart"), ShoppingCart).Orders.RemoveAt(e.RowIndex())
BindData()
End Sub


And that is it! You should now be able to view the contents of your ShoppingCart or other ArrayList in GridView form, and make easy edits and deletes.


How To Fill a GridView with Custom Objects from an Arraylist using a DataTable

0 comments:

Post a Comment