OT: Databinding

OT: Databinding

Old forum URL: forums.lhotka.net/forums/t/2342.aspx


SultanOfSuede posted on Wednesday, February 14, 2007

The data binding for objects in .net 2.0 looks powerful, but I've noticed that all the samples studiously avoid cases where the properties of the objects being bound are something other than primitive types.

If I have a Customer class with a property of type Address, then binding to a grid becomes problematic.  At run time, the Customer.Name property will bind to a column but the Address will have its ToString() method called and I get something like MyCompany.Library.Address instead of what I really want, the Address.StreetOne property.   I've not seen anything in the designers  that will allow me to bind to a child object's property. 

If I want to have a grid that just shows this:

Customer Name     Address
------------------------------------------------------
John Doe               123 Main St.

How do I specify that Address is really referring to Address.StreetOne? 

Are people just flattening their bound objects instead?

Thx in advance

Brian Criswell replied on Wednesday, February 14, 2007

Working off of the top of my head, you should just be able to bind to Customer.Address.StreetOne.

McManus replied on Wednesday, February 14, 2007

Hi,

I think Brian is right. I've not used it in a grid, but I was able to bind Customer.Address.StreetOne (at least something similar) to the Text property of a TextBox.

Cheers,

Herman

robert_m replied on Thursday, February 15, 2007

Hi everyone

Yes, you can bind a TextBox to Customer.Address.StreetOne but you can not bind a grid column to a child object (nested) property. I tried this with both MS DataGridView and DevExpress grid and it doesn't work (you get empty cells).

For the time being, I use additional properties in CSLA objects, for instance if you want to see Customer.Address.Street in datagrid you can always create additional string property in Customer class like this:

public string AddressStreet

{

   get { return Address.Street; }

}

This is a bit awkward and it diminishes the elegance of code :), but it works.. 

DansDreams replied on Thursday, February 15, 2007

I'm not clear, are you trying to bind the whole child object to the column, or are you saying simply that you can't enter Customer.Address.StreetOne as the binding source for a column?

ajj3085 replied on Thursday, February 15, 2007

You could also create a second BindingSource, and set its datasource property equal to the object.Childbobject.  In design time, you just set the datasource for the bindingsource to the ChildObject class.  That should allow you to work with the databinding in the designer as you'd expect.

HTH
Andy

SultanOfSuede replied on Thursday, February 15, 2007

For grids, I found a couple of solutions by consulting technical support at Infragistics. I'm not sure whether it would work for all grids, but I offer it here as a resource.

You can override the ToString() method of each object to return only the property.  By default, when bound, the child reference property (Customer.Address) just emits its type as a string, so the column ends up with MyCompany.MyApp.Customer.Address.  Overriding the ToString() to return StreetOne of the Address object will instead show something like "123 Main Street."  This works in a pinch but is not elegant.

The second and more cumbersome approach involves using unbounded columns in addition to the bound columns.  With the Infragistics UltraWinGrid, you simply write code in InitializeLayout event that adds an additional column(s) to your grid.  These will show the actual values of the child properties.  The original bound column (Customer.Address) has to be hidden so that the unbounded column can show its primitive property (Customer.Address.StreetOne).

Next, you have to write a handle for the InitializeRow event.  This is where you will actually assign the property values to the columns added in the previous step.  This works because the event fires for each row as its added to the grid.  The Value property of each cell is of type object and can be cast to the exact type it's actually bound to at runtime.  From there, you can get the property you need.

Here's a code snippet:

        void lstCustomers_InitializeRow(object sender, Infragistics.Win.UltraWinGrid.InitializeRowEventArgs e)
        {
            e.Row.Cells["Address"].Value = ((Address)e.Row.Cells["Address"].Value).StreetOne;
        } 


The final grid would look like this, with the last column being generated through the sample code just given:

Customer       Address (hidden object)                                  Address.StreetOne (unbounded column)
-------------------------------------------------------------------------------------------------------
John Doe      MyCompany.MyApp.Customer.Address         123 Main St.

HTH,

Ian

Copyright (c) Marimer LLC