Vault of Thoughts

2006-07-21

Please visit my new blog at vaultofthoughts.net

Using Bind with nested properties

ASP.NET 2.0 comes with a mechanism called two way databinding which allows us to declaratively bind a form element to a property of an object in such way that updates are supported. For the readonly display you typically use the Eval method in your aspx page. For the two way mechanism, you use the Bind keyword (or method?).


Using the Bind keyword is really simple in most scenarios that you encounter, especially if you are using the SqlDataSource control. Problems start to come up when you try to use a more object oriented approach and use the ObjectDataSource control.


Now, still in most cases using ObjectDataSource will not cause you any problems when what u bind is a simple property such as a name of a client i.e.: you have a collection of clients that you bind to a GridView and one of the columns displays the name of the client. To do so you use something like Bind("Name"). The problem arises when you need to bind to a subproperty such as in Bind("Address.StreetName"). This won't work unfortunatelly...


Why it is not possible to perform a two way databinding in such a way, there are discussions over the Internet. BTW: Eval("Address.StreetName") works as expected. So what can we do about it? Of course there is a solution for this problem and it has came to me when I was thinking why there is no such a problem when you use the SqlDataSource control.


The reason why there is no such problem when you are working with relational data is that you are creating an SQL query that is a VIEW of the data that you want to display i.e.: it has all the columns you need and there are no "sub-columns". So what we need to do is to translate this to an object world.


So basically what we need to do is create an object that will serv as a view on our objects and bind to this view object. For example given the aforementioned client object with a name and an address we create a ClientView object that encapsulates our client object and exposes the needed properties such as Name or StreetName. Those properties in turn call on the properties of the client object either directly as in Name or to some nested property as in Address.StreetName.


Making a select method used by the DataSourceControl to return the collection of ClientView object should not pose any problem. When using such a technique I would suggest putting the view classes somewhere outside the domain model since the only reason they exist is to allow for the two way databinding to work so there is no reason to pollute the model.


kick it on DotNetKicks.com

If you liked this article why not support its author by making a donation?

5 Comments:

  • Check out the ObjectViews project, it was designed to handle exactly this problem.

    http://sourceforge.net/projects/objectviews

    By Blogger Orand, at 8:59 PM  

  • I have checked the ObjectViews but it seems that it is very WinForms oriented solution. I'm not a WinForms lover myself unfortunatelly :-(

    By Blogger Mikeon, at 9:14 PM  

  • I did as you described:
    1. I have an objectA, which holds the instance of objectB.
    2. ObjectB has some public properties.
    3. I have a FormView, which is bound to ObjectA.

    I have a problem with displaying properties of ObjectA:
    %# Eval("CustomerBankAccount.BankAccountNo") % - this works

    %# Bind("CustomerBankAccount.BankAccountNo") % - this not.

    What is wrong with it?

    By Anonymous Anonymous, at 12:07 PM  

  • Actually what you should do is on ObjectA create a property like this:
    public string ObjectABankAccountNo
    {
    get { return this.objectB.BankAccountNo; }
    }

    and then when binding declaratively to ObjectA use this propert as follows:
    %# Bind("ObjectABankAccountNo") %

    By Blogger Mikeon, at 1:20 PM  

  • A workaround for MS non OO work with the objectdatasource is to manipulate the buissnessobject in the objectDataSource_Updating event. I dont like the idea of creating some sort of new "binding-objects" that make my objectmodell smell.....
    Cast your object (Custom customer= (Customer)e.InputParameters[0]) and set the nested objectparameters/properties.
    I use this when I have a simple object like "adress" on my masterobject. When I have collections i usually use a new objectdatasource that handles the binding using ID:s of the masterobject or its childs.

    By Anonymous Anonymous, at 3:57 PM  

Post a Comment

Links to this post:

Create a Link

<< Home