Fun ASP.NET Whidbey Tip/Trick: DataBinding to Generics

One of the great new features in Whidbey are "Generics" -- which basically provide a mechanism that enables developers to build classes whose signature and internal datatypes can be templatized.

For example, rather than use an ArrayList (which is a collection of type Object), or force developers to create their own strongly typed list collection class (ie: the OrderCollection class) -- developers using Whidbey can use the new List class implemented within the System.Collections.Generic namespace, and specifically specify the type of the collection when using or referencing it.

For example:

// Use the built-in "List" collection within the System.Collections.Generic namespace
// to create a collection of type "Order"

List<Order> orders = new List<Order>();

// Add Order objects into the list

orders.Add(new Order(123, "Dell"));
orders.Add(new Order(345, "Toshiba"));
orders.Add(new Order(567, "Compaq"));

// Lookup the "OrderId" of the first item in the list -- note that there is no cast below,
// because the collection items are each an "Order" object (as opposed to "Object"
// which they would be with an ArrayList

int orderId = orders[0].OrderId

// The below statement will generate a compile error, but would have
// compiled (but generated a runtime exception) if the collection was
// an ArrayList

orders.Add("This will not work because it isn't an order object");


--------------------------------------------------

Below is a more complete sample on how to use Generics with the new ASP.NET ASP:ObjectDataSource control, and then bind the list to a GridView control.

First is the "OrderSystem.cs" file which should be saved within the "Code" directory immediately underneath the application vroot:
// OrderSystem.cs: Save within "code" directory

using System; using System.Collections.Generic;

public class Order { private int _orderId; private string _productName;
public Order(int orderId, string productName) { _orderId = orderId; _productName = productName; }
public string ProductName { get { return _productName; } }
public int OrderId { get { return _orderId; } } }
public class OrderSystem { public List<Order> GetOrders() { List<Order> orders = new List<Order>();
orders.Add(new Order(123, "Dell")); orders.Add(new Order(345, "Toshiba")); orders.Add(new Order(567, "Compaq"));
return orders; } }
I can then write a simple .aspx page that uses the ObjectDataSource control to bind against the "GetOrders" method to retrieve a List of Order objects. I can then point the GridView at the ObjectDataSource control:

<%@ page language="C#" %>
<html> <body> <form runat="server"> <asp:gridview id="GridView1" runat="server" datasourceid="ObjectDataSource1" bordercolor="#CC9966" borderstyle="None" borderwidth="1px" backcolor="White" cellpadding="4"> <headerstyle forecolor="#FFFFCC" backcolor="#990000" font-italic="False" font-bold="True"> </headerstyle> </asp:gridview>
<asp:objectdatasource id="ObjectDataSource1" runat="server" typename="OrderSystem" selectmethod="GetOrders"> </asp:objectdatasource>
</form> </body> </html>

7 Comments

  • I would not call this a fun trick, Scott. It is basic generics behavior. WHich, by no means, is meant to be negative towards this. I mean, thank whoever you bliaeve in that we finally do get generics in the .NET Framework.



    You know the one REALLY negative thing? Whidbey is still so far away to be usable in a real project. I with I could just give up a year now.

  • Thanks for the good coding example. It'll be interesting to see some comparisons for performance (with the use of ArrayList, user-type class collection, etc).

  • Regarding performance, aren't these just compiler tricks? There shouldn't be a whole lot of runtime performance cost for this, should there?



    Also, what &quot;STLisms&quot; do generics introduce to the managed world with regard to collections? Can we expect some of the same caveats, or is there something about running in managed memory space that will insulate us from some of the tricky situations as outlined in the book &quot;Effective STL&quot;?

  • Hi Scott,

    Unfortunately I don't know of an automatic way to-do this. I think you'd probably need to write a helper function to handle it.

    Sorry!

    Scott

  • Do you have any idea why it is that if I return a list of Strings (instead of a class like Orders), instead of objects, the only field I can bind to is the Length of the string, not the Value.

    If I Bind at runtime using the DataSource and DataBind methods I see the string values, but if I use the ObjectDataSource, the only field available is Length.

    -Rd

  • Hi Richard,

    How are you binding against the value? You should be able to bind against the value.

    Thanks,

    Scott

  • Is it possible to get the ObjectDataSource to call an update method in OrderSystem such as:

    public void SaveOrders(List changedOrders)
    {
    // Do save here
    }

    Can the ObjectDataSource pass in the changed list of orders? Every time I try it there are no elements in the generic list.

Comments have been disabled for this content.