Lance Ahlberg's WebLog

Reflection on reason

Binding the GridView control to a complex (deep) business object

MSDN Magazine features a new ASP.NET 2.0 Grid control called GridView.

http://msdn.microsoft.com/msdnmag/issues/04/08/GridView/default.aspx

I have been working with this control in conjunction with an ObjectDataSource in order to display data directly from a domain object.  The GridView in combination with the DataObjectSource allows me to pursue an object driven design in my applications.

I initially setup the GridView in design mode with Bound Fields.  To add the bound fields, I used the field dialog, accessible by clicking on the expand button on the Columns property of the gridView.

This worked fine so long as the domain object that was linked to the ObjectDataSource was “flat”.

So if I had a class...

public OrderItem
{
 private string productName;
 public string ProductName
 {
  get
  {
   return productName;
  }
  
  set
  {
   productName = value;  
  }
 }

 private int orderQuantity;
 public int OrderQuantity;
 {
  get
  {
   return orderQuantity;
  }
  
  set
  {
   orderQuantity = value;
  }
 }

 private decimal productPrice;
 public decimal ProductPrice;
 {
  get
  {
   return productPrice;
  }
  
  set
  {
   productPrice = value;
  }
 }
  
 public OrderItem()
 {
  productName ="";
  orderQuantity = 0;
  productPrice = 0.00M;
 }

}

I can then set the BoundFields DataField property to the OrderItem object properties  ie ProductName, OrderQuantity, or ProductPrice.

But what happens when I have a domain object that is composed of other referenced objects...

public Product
{
 private string name;
 public string Name
 {
  get
  {
   return name;
  }
  
  set
  {
   name = value;  
  }
 }

 private decimal price;
 public decimal Price;
 {
  get
  {
   return price;
  }
  
  set
  {
   price = value;
  }
 }
  
 public Product()
 {
  name ="";
  price = 0.00M;
 }

}

public OrderItem
{
 private Product associatedProduct;
 public Product AssociatedProduct
 {
  get
  {
   return associatedProduct;
  }
  
  set
  {
   associatedProduct= value;  
  }
 }

 private int orderQuantity;
 public int OrderQuantity;
 {
  get
  {
   return orderQuantity;
  }
  
  set
  {
   orderQuantity = value;
  }
 }

 public OrderItem()
 {
  associatedProduct=null;
  orderQuantity = 0;
 }

}

Now when I set the BoundFields DataField property to the Products properties via the OrderItems AssociatedProduct property ie AssociatedProduct.Name or AssociatedProduct.Price the bound field displays a nothing.

In order to get this to work I had to use a TemplateField instead of a BoundField. The field dialog has a nifty link button that can be used to convert the BoundField to a TemplateField. 

All I had to do was create a bound field with a DataField property of AssociatedProduct.Name and then press the “Convert this field into a Template Field“ button and presto the product name was now displaying.

Magic I say..

 

 

Comments

ceylon said:

The times of continually hunting for legit inclinations having to do with this idea are finished.

# September 28, 2007 5:37 AM

jm said:

hi, when i convert the boundfield to a templatefield it throw a ex.

[City.name is not ....

i have a Country Object with a city object inside and i want to populate country and city in the same gridview.

# November 21, 2007 10:20 AM

Binding the GridView control to a complex (deep) business object said:

Pingback from  Binding the GridView control to a complex (deep) business object

# November 25, 2007 8:14 PM

xxxxx said:

xcxcxc xcx cxcx cxcx cxcx cxcx cx cxc cxcxcxdsds dsds sasa sasa qwq wqwq wqwq wqwq

# April 11, 2008 12:44 PM

Me said:

This doesn't work.

# June 29, 2008 10:31 PM

sprlengchai said:

Well, in your grid view should write as bellow:

<%# DataBinder.Eval(DataBinder.Eval(Container.DataItem, "AssociatedProduct"), "Name")%>

please try..

# August 20, 2008 11:38 PM

Ricardo Rief said:

It works perfectly for me!

Thank you!

# October 22, 2008 8:25 AM

Ricardo Rief said:

Now I found another problem...

How can I set this same property AssociatedProduct.Name as a DataKeyName?

Thanks.

# January 9, 2009 2:12 PM

sprlengchai said:

Sure. Solution as bellow. pls try again.

<%# DataBinder.Eval(Container.DataItem, "AssociatedProduct.Name") %>

# February 22, 2009 5:28 AM

Habeeb said:

Remove the "[" "]" from the property name ([City.name]) and it work.

By the way, nice post dude.

Sometimes we need to spend hours to resolve silly issues with Microsoft products.

http://www.habeebonline.com

# July 31, 2009 7:41 PM

Ovidiu Petruescu said:

The easiest way to do this is to extend the BoundField and provide your own implementation for GetValue

For Example:

public class EnhancedBoundField : BoundField

   {

       protected override object GetValue(Control controlContainer)

       {

           object component = null;

           string dataField = this.DataField;

           if (controlContainer == null)

           {

               throw new HttpException("DataControlField_NoContainer");

           }

           component =  DataBinder.GetDataItem(controlContainer);

           if ((component == null) && !base.DesignMode)

           {

               throw new HttpException("DataItem_Not_Found");

           }

           // use reflection to get the data from your child...

       }

   }

# August 14, 2009 1:55 AM
Leave a Comment

(required) 

(required) 

(optional)

(required)