Extending the GridView — Part I

Most business applications require presenting result sets to the end users in the form of some kind of grid views. While the default ASP.NET GridView control is sufficient for simple scenarios when doing rapid application development, its drawbacks become clear when building any large scale solutions (discussions here apply to all the current .Net frameworks, 2.0, 3.5 etc.).

For instance, the default data binding is limited to SqlDataSource, ObjectDataSource or a DataSet object (including DataView, DataTable, etc.). When building a large scale business solution, it is generally desirable to complete separate the data manipulation and business logic from the presentation layer and the most common solution is to employee a Model-View-Controller pattern.  This requirement makes SqlDataSource and DataSet bindings unsuitable. While ObjectDataSource does provide some level of isolation, the way business objects can be constructed is limited in order for these objects to be used as ObjectDataSource.

Most business objects incorporate the so-called Value Object data structure. Basically, it is a serializable class with the sole purpose of holding values and possibly other functionalities like data validation. Unfortunately, by default, GridView’s support for such value objects is poor (i.e. you can bind a value object to a grid view, but sorting is not supported by default). Over the years, I have seen many ad-hoc implementations to make GridView suitable for binding with customized value objects. Unfortunately, many of the solutions were implemented poorly and the implementation techniques vary from person to person, making it difficult if not impossible to maintain.

In the next few blog posts, I will show you how to extend the stock GridView in ASP.Net to make it suitable for using with value objects. The goal of extending the standard GridView is not only to add sorting capabilities, but to make the new component compatible with the standard GridView. I also intended to hide as much implementation details as possible so that the end users do not need to worry about the syntactical nuances as do with the standard GridView when binding to objects.

I assume that the development environment is Visual Studio 2005 with AJAX extension installed. The samples I show here can run within either Visual Studio 2005 (with AJAX extension) or Visual Studio 2008 without any modifications.

1.Defining the Value Object

As mentioned before, the reason we would like to define our own so-called value objects instead of using a DataSet to hold data is to ensure type safety. Since DataSet can hold any kind of objects, debugging becomes more difficult as error checking happens at run time not compile time. It also makes it easy to make mistakes as columns must be accessed by their names and any changes in column names could result in code broken at runtime somewhere in the UI.  Most importantly, binding a dataset directly to the UI violates the layered design principal, making the data and the presentation tightly coupled and difficult to adapt. The solution is to create a level of indirection by utilizing the so called value objects. Value objects are nothing fancy, they are merely a serializable class that provides the properties that represent the data (e.g. a row in a table) we are dealing with. For instance, here is what we might create as a value object for a simple phone book:

 

    [Serializable()]
    public class ItemVal
    {
        string _name = string.Empty;
        string _address = string.Empty;
        string _zipCode = string.Empty;
        string _phoneNumber = string.Empty;
        bool _selected = false;
 
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }
 
        public string Address
        {
            get { return _address; }
            set { _address = value; }
        }
 
        public string ZipCode
        {
            get { return _zipCode; }
            set { _zipCode = value; }
        }
 
        public string PhoneNumber
        {
            get { return _phoneNumber; }
            set { _phoneNumber = value; }
        }
 
        public bool Selected
        {
            get { return _selected; }
            set { _selected = value; }
        }
 
        public ItemVal(string name, string address, string zipCode, string phoneNumber)
        {
            _name = name;
            _address = address;
            _zipCode = zipCode;
            _phoneNumber = phoneNumber;
        }
    }

By creating a collection of such value object we just defined, we have a full representation of the result set returned from the database via a query or stored procedure. And via value objects, all the accesses are guaranteed to be type safe.

See also

Code Download: ExtendingTheGridView.zip

Be Sociable, Share!

Leave a Reply