Gridview databinding with nested types

R

Richard Gannon

Hi all,

Is there an *easy* way to use declarative databinding when biniding an
ASP.NET 2.0 Gridview to an ObjectDataSource that consumes custom
entities that contain nested types??

For Example, suppose I have the following classes in my BLL (Business
Logic Layer):
(Note: this is made-up code, but should demonstrate the issue).


public class Customer
{
string _customerTitle = "";
string _customerForename = "";
string _customerSurname = "";
Address _customerAddress = null;

public string CustomerTitle
{
get {return _customertitle;}
set {_customerTitle = value;}
}

public string CustomerForename
{
get { return _customerForename; }
set { _customerForename = value; }
}

public string CustomerSurname
{
get { return _customerSurname; }
set { _customerSurname = value; }
}

public Address CustomerAddress
{
get
{
if (_customerAddress == null)
_customerAddress = [Code to retrieve customer's
address from DAL];
return _customerAddress;
}

}
}


public class Address
{
string _address1 = "";
string _address2 = "";
string _address3 = "";
string _postcode = "";

public string Address1
{
get { return _address1; }
set { _address1 = value; }
}

public string Address2
{
get { return _address2; }
set { _address1 = value; }
}

public string Address3
{
get { return _address3; }
set { _address1 = value; }
}

public string Postcode
{
get { return _postcode; }
set { _postcode = value; }
}
}



As you can see, the "Customer" type contains a number of simple types
for the customer's forename, surname etc. and also contains a property
which exposes a "nested type" of the Address type.

In code, I can happily do things like the following:

_customer.Forename = "John";
_customer.Surname = "Smith";
_customer.Address.Address1 = "123 High Street";
_customer.Address.Postcode = "ZZ1 99C";

However, I'm fairly certain that when binding a "Customer" object (via
an ObjectDataSource) to a Gridview, and using declarative databinding
techniques, you *cannot* specify something like the following:
(Again, made-up code, but should demonstrate the issue)

<asp:GridView ID="grvCustomers" runat="server"
DataSourceID="odsCustomers">
<Columns>
<asp:BoundField DataField="CustomerTitle"
HeaderText="Customer Title"/>
<asp:BoundField DataField="CustomerTitle"
HeaderText="Customer Forename"/>
<asp:BoundField DataField="CustomerTitle"
HeaderText="Customer Surname"/>
<asp:BoundField DataField="Address.Postcode"
HeaderText="Customer Postcode"/>
</Columns>
</asp:GridView>
<asp:ObjectDataSource ID="odsCustomers" runat="server"
SelectMethod="GetCustomers" TypeName="Customer">
</asp:ObjectDataSource>

Note the line that tries to use "Address.Postcode" as the value for
the "DataField" attribute. This will fail.


Is there an easy way to achieve this using declarative techniques?
I'm aware that I can programmatically bind the various "Customer"
properties and the properties of the nested "Address" type to the
Gridview's columns, but I'm looking for a way to achieve this without
having to resort to programmatic binding.


Thanks in advance.



Regards,
Richard.
 
N

Nicholas Paldino [.NET/C# MVP]

Richard,

Out of the box, it doesn't seem like there is a way to do this with the
controls provided. The two ideas I could come up with would be to either
create an intermediary object which would expose the properties you want to
bind to, which only has one layer of properties, or, create a custom
BoundField implementation (I am not sure that this would work, as I've never
tried it, but there seems to be a few protected methods which would allow
you to get at what you want).


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Richard Gannon said:
Hi all,

Is there an *easy* way to use declarative databinding when biniding an
ASP.NET 2.0 Gridview to an ObjectDataSource that consumes custom
entities that contain nested types??

For Example, suppose I have the following classes in my BLL (Business
Logic Layer):
(Note: this is made-up code, but should demonstrate the issue).


public class Customer
{
string _customerTitle = "";
string _customerForename = "";
string _customerSurname = "";
Address _customerAddress = null;

public string CustomerTitle
{
get {return _customertitle;}
set {_customerTitle = value;}
}

public string CustomerForename
{
get { return _customerForename; }
set { _customerForename = value; }
}

public string CustomerSurname
{
get { return _customerSurname; }
set { _customerSurname = value; }
}

public Address CustomerAddress
{
get
{
if (_customerAddress == null)
_customerAddress = [Code to retrieve customer's
address from DAL];
return _customerAddress;
}

}
}


public class Address
{
string _address1 = "";
string _address2 = "";
string _address3 = "";
string _postcode = "";

public string Address1
{
get { return _address1; }
set { _address1 = value; }
}

public string Address2
{
get { return _address2; }
set { _address1 = value; }
}

public string Address3
{
get { return _address3; }
set { _address1 = value; }
}

public string Postcode
{
get { return _postcode; }
set { _postcode = value; }
}
}



As you can see, the "Customer" type contains a number of simple types
for the customer's forename, surname etc. and also contains a property
which exposes a "nested type" of the Address type.

In code, I can happily do things like the following:

_customer.Forename = "John";
_customer.Surname = "Smith";
_customer.Address.Address1 = "123 High Street";
_customer.Address.Postcode = "ZZ1 99C";

However, I'm fairly certain that when binding a "Customer" object (via
an ObjectDataSource) to a Gridview, and using declarative databinding
techniques, you *cannot* specify something like the following:
(Again, made-up code, but should demonstrate the issue)

<asp:GridView ID="grvCustomers" runat="server"
DataSourceID="odsCustomers">
<Columns>
<asp:BoundField DataField="CustomerTitle"
HeaderText="Customer Title"/>
<asp:BoundField DataField="CustomerTitle"
HeaderText="Customer Forename"/>
<asp:BoundField DataField="CustomerTitle"
HeaderText="Customer Surname"/>
<asp:BoundField DataField="Address.Postcode"
HeaderText="Customer Postcode"/>
</Columns>
</asp:GridView>
<asp:ObjectDataSource ID="odsCustomers" runat="server"
SelectMethod="GetCustomers" TypeName="Customer">
</asp:ObjectDataSource>

Note the line that tries to use "Address.Postcode" as the value for
the "DataField" attribute. This will fail.


Is there an easy way to achieve this using declarative techniques?
I'm aware that I can programmatically bind the various "Customer"
properties and the properties of the nested "Address" type to the
Gridview's columns, but I'm looking for a way to achieve this without
having to resort to programmatic binding.


Thanks in advance.



Regards,
Richard.
 
R

Richard Gannon

Hi Nicholas,

I have actually found one way to achieve this with declarative coding,
and that is to use a TemplateField, rather than a BoundField, and then
to use the Databinder.Eval method to "look-up" the desired property.
This works very well with nested types.

For example, if my ObjectDataSource is bound to a type named
"Customer", I can use the following declarations in my ASPX page,
within the "TemplateField" of a Gridview:

<asp:Label runat="server" ID="lblName">Customer ForeName:
<%#Eval("CustomerForename")%></asp:Label>

Which displays the Customer Forename property of the "Customer" type,
and then also:

<asp:Label runat="server" ID="lblAddress1">Address 1:
<%#Eval("CustomerAddress.Address1")%></asp:Label>

Which displays the Address1 property of the "nested" Address type.

This works beautifully, but of course, the downside here is that by
using the Databinder and the Eval method, everything is late-bound,
however, for my purposes I can live with this.

Does anyone know of a way of achieving this using early-bound
declarations?? I'm not so sure it's possible, but I'd like to be
proven wrong! :)

Regards,
Richard.



Richard,

Out of the box, it doesn't seem like there is a way to do this with the
controls provided. The two ideas I could come up with would be to either
create an intermediary object which would expose the properties you want to
bind to, which only has one layer of properties, or, create a custom
BoundField implementation (I am not sure that this would work, as I've never
tried it, but there seems to be a few protected methods which would allow
you to get at what you want).
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Richard Gannon said:
Hi all,

Is there an *easy* way to use declarative databinding when biniding an
ASP.NET 2.0 Gridview to an ObjectDataSource that consumes custom
entities that contain nested types??

For Example, suppose I have the following classes in my BLL (Business
Logic Layer):
(Note: this is made-up code, but should demonstrate the issue).


public class Customer
{
string _customerTitle = "";
string _customerForename = "";
string _customerSurname = "";
Address _customerAddress = null;

public string CustomerTitle
{
get {return _customertitle;}
set {_customerTitle = value;}
}

public string CustomerForename
{
get { return _customerForename; }
set { _customerForename = value; }
}

public string CustomerSurname
{
get { return _customerSurname; }
set { _customerSurname = value; }
}

public Address CustomerAddress
{
get
{
if (_customerAddress == null)
_customerAddress = [Code to retrieve customer's
address from DAL];
return _customerAddress;
}

}
}


public class Address
{
string _address1 = "";
string _address2 = "";
string _address3 = "";
string _postcode = "";

public string Address1
{
get { return _address1; }
set { _address1 = value; }
}

public string Address2
{
get { return _address2; }
set { _address1 = value; }
}

public string Address3
{
get { return _address3; }
set { _address1 = value; }
}

public string Postcode
{
get { return _postcode; }
set { _postcode = value; }
}
}



As you can see, the "Customer" type contains a number of simple types
for the customer's forename, surname etc. and also contains a property
which exposes a "nested type" of the Address type.

In code, I can happily do things like the following:

_customer.Forename = "John";
_customer.Surname = "Smith";
_customer.Address.Address1 = "123 High Street";
_customer.Address.Postcode = "ZZ1 99C";

However, I'm fairly certain that when binding a "Customer" object (via
an ObjectDataSource) to a Gridview, and using declarative databinding
techniques, you *cannot* specify something like the following:
(Again, made-up code, but should demonstrate the issue)

<asp:GridView ID="grvCustomers" runat="server"
DataSourceID="odsCustomers">
<Columns>
<asp:BoundField DataField="CustomerTitle"
HeaderText="Customer Title"/>
<asp:BoundField DataField="CustomerTitle"
HeaderText="Customer Forename"/>
<asp:BoundField DataField="CustomerTitle"
HeaderText="Customer Surname"/>
<asp:BoundField DataField="Address.Postcode"
HeaderText="Customer Postcode"/>
</Columns>
</asp:GridView>
<asp:ObjectDataSource ID="odsCustomers" runat="server"
SelectMethod="GetCustomers" TypeName="Customer">
</asp:ObjectDataSource>

Note the line that tries to use "Address.Postcode" as the value for
the "DataField" attribute. This will fail.


Is there an easy way to achieve this using declarative techniques?
I'm aware that I can programmatically bind the various "Customer"
properties and the properties of the nested "Address" type to the
Gridview's columns, but I'm looking for a way to achieve this without
having to resort to programmatic binding.


Thanks in advance.



Regards,
Richard.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top