Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Binding sub Objects to DataField and DataSource

Tags:

c#

asp.net

class A 
{ 
  int ID; 
  B ClassB; 
}

class B 
{ 
  string Title; 
}

Using the above mock classes as examples - I have a dynamically created GridView. To this I bind (add to the Columns collection) X number of BoundFields and then assign a collection to the DataSource, however, my sub objects are not binding.

The DataField property of the BoundFields is set to "ClassB.Title" and the DataSource is a collection of objects of type A but it keeps throwing the exception "A field or property with the name 'ClassB.Title' was not found on the selected data source. "

Any thoughts why?

Cheers

like image 686
johnnyboy Avatar asked Oct 11 '11 07:10

johnnyboy


1 Answers

This is because BoundField uses reflection to evaluate object properties - obviously, class A does not have a property called ClassB.Title and hence the issue.

You can use template field to work around this issue. For example,

<asp:templatefield headertext="SomeColumn">
     <itemtemplate>
          <%#Eval("ClassB.Title")%>
     </itemtemplate>
</asp:templatefield>

Note that instead of using typical template-field markup such as below, you may use strongly typed expressions such as

<asp:templatefield headertext="SomeColumn">
     <itemtemplate>
          <%# ((A)(Container.DataItem)).ClassB.Title  %>
     </itemtemplate>
</asp:templatefield>

Note the type-casting of data-item to your specific class (A).

EDIT: yet another alternative is to build your own BoundField that can do nested property lookup - for example:

public class MyBoundField : BoundField
{
   protected override object GetValue(Control controlContainer)
   {
      string dataField = this.DataField;
      if (string.IsNullOrEmpty(dataField)) { return null; }
      if (!dataField.Contains('.'))
      {
         // use base implemenation
         return base.GetValue(controlContainer);
      }

      // design time support
      if (base.DesignMode)
      {
        return this.GetDesignTimeValue();
      }

      // Use data-binder to evaluate nested property look-ups
      return DataBinder.Eval(controlContainer, dataField);
   }

}
like image 149
VinayC Avatar answered Nov 14 '22 21:11

VinayC