Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

A Grid for Domain Objects

4.25/5 (5 votes)
18 May 2008CPOL4 min read 1   276  
A practical grid for domain objects to be used in WinForms systems.

Introduction

One of the advantages of working with Windows Forms applications is the ability to include domain objects directly into UI components as it is done with dropdowns and listboxes, for example. Among UI components, tabular grids are very useful since they provide a broad view from an information perspective, and are very much used in CRUD windows.

Let's suppose a system is asked to be built with a grid of categories with some relevant information. A Category class is already available, and is declared as a POCO class with the following C# code:

C#
using System;

namespace DomainObjects
{
    public class Category
    {
        private long _id;
        public virtual long Id
        {
            get { return this._id; }
            set { this._id = value; }
        }

        private string _categoryName;
        public virtual string CategoryName
        {
            get { return this._categoryName; }
            set { this._categoryName = value; }
        }

        private string _description;
        public virtual void SetDescription(string description)
        {
            this._description = description;
        }
        public virtual string GetDescription()
        {
            return this._description;
        }       
    }
}

For that purpose, in the .NET framework, we can find the DataGrid. In order to display objects data in a DataGrid, the DataSource property must receive a collection of these objects.

C#
IList<category> lstCategories = PopulateCategoriesList(lstCategories);
this.dataGridView1.DataSource = lstCategories;

As a result of a list of Categories, the following grid is obtained:

A_Grid_for_Domain_Objects_html_m12abf3ee.gif

Note that the DataGrid component can only see the properties Id and CategoryName and display their contents as columns.

The DataGrid presents the following disadvantages when used with a collection of objects:

  • It is very restrictive is terms of reflective mappings since it can only see public properties as columns in the grid, making it not possible to be used in a big variety of situations with objects;
  • Configuring column features such as headers and widths is not an intuitive task;
  • It is not possible to traverse an object association to display data from another object in a higher depth;

In order to overcome these drawbacks, this article proposes a grid for Domain Objects capable of mapping fields and associations between objects to columns in a grid table, referred as ObjectGrid.

Sample Usage

To use ObjectListGrid, first, you should drag the component to your window and rename it as gridResults. After replacing the grid above with an ObjectGrid named as gridResults, it must be configured before receiving its object items.

C#
// Domain Grid Mappings for Category Class ( or any class with the members below ) 
this.gridResults.AddColumn(new string[] {"CategoryName"},"Name",80);      
this.gridResults.AddColumn(new string[] {"GetDescription"}, "Description", 200);
// Domain Grid receives collection of Categories as a Datasource
this.gridResults.DataSource = PopulateCategoriesList();

Below shown is the resulting grid:

A_Grid_for_Domain_Objects_html_m49dd997a.gif

Transforming the Object Graph into a Grid Table

The ObjectGrid is a .NET User Component that wraps a DataGrid. It has methods to describe column characteristics, and must receive a collection of objects as a DataSource.

These columns are mapped into values by a chain of member names, which is used by the component to traverse the object graph from the object in the collection, to get a specific data of the final object in the chain through Reflection.

A_Grid_for_Domain_Objects_html_5f2c87a3.gif

Since it uses reflective information of member names, the same ObjectGrid can be used to display different types of objects, provided that they contain these members' names.

Another Usage

Take, for example, a grid of Suppliers taken from the UML below:

A_Grid_for_Domain_Objects_html_m2cd7c8a6.jpg

In this grid, it is asked to display the following data from the suppliers: company name, phone, street, city, state and country.

Four steps are necessary to use this component in a Windows Forms application:

  1. Drag the component in the desired space in a Windows form.
  2. A_Grid_for_Domain_Objects_html_6892aa91.gif

  3. Add the columns describing the title, length, and object members.
  4. C#
    this.gridResults.AddColumn(new string[]{"CompanyName"},"Name",80);
    this.gridResults.AddColumn(new string[]{"ContactName"},"Contact",90);
    this.gridResults.AddColumn(new string[]{"Phone"},"Phone",50);
    this.gridResults.AddColumn(new string[]{"HomePage"},"Home Page",110);
    this.gridResults.AddColumn(new string[]{"Street","Name"},"Street",50);
    this.gridResults.AddColumn(new string[]{"Street","City","Name"},"City",50);
    this.gridResults.AddColumn(new string[]{"Street","City","State","Name"},"State", 50);
    this.gridResults.AddColumn(new string[]{"Street","City", "State","Country", 
                               "Name"},"Country",50);

    If you know this grid will be used only for suppliers, the columns can be added to the grid in the form initialization.

    The first parameter is an array of member names (be it a method, property, or field). The second is the column title, and the third is the column width. The first parameter is also the key aspect of this grid. The map method is responsible for mapping the columns of the domain grid navigating through the object graph in memory.

    For example, in order to get a supplier's city name, it is necessary to execute supplier.Street.City.Name. Thus, the column Street is mapped as {“Street”,”City”,”Name”}.

    Theoretically, the ObjectGrid is capable of navigating through object associations of N-depth, and the only requirement in order to avoid exceptions from this component is that the object must have the mapped member name implemented, and that the member return value implements the forward member name, and so on.

  5. Set a collection of objects to the component. Each object must implement the mapped members.
  6. C#
    this.olstgResults.DataSource = PopulateSuppliersList();

Adding, Updating, and Removing Objects to the Grid

In order to modify the data displayed by the grid, new objects can be added or removed from the grid with the Item property.

C#
// Adding new element to the grid
this.gridResults.Items.Add(category); 
           
// Removing element from the grid
this.gridResults.Items.Remove(category);

When an object inside the list is altered, the grid must be notified with the method UpdateView.

C#
// Refreshing grid
category.SetDescription("New description");
this.gridResults.Refresh();

Recovering Selected Object

Besides easy configuration to view the data, another advantage of working with the ObjectGrid is that the object that represents a selected line can be recovered to the application.

After selecting a grid line, like this:

A_Grid_for_Domain_Objects_html_5a89fa18.gif

the selected object can be recovered with the CurrentObject property:

C#
object selectedObject = this.gridResults.CurrentObject;

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)