I have a custom Object A, which has a reference to the Object B and two string type properties lets say Prop1,Prop2. Object B also has a string property called prop3. Now when I bind the A to UltraWingrid.
So i have a nested object structure. In my grid, Now I want three columns , third column with the value of prop3 of Object B.
I am trying to change the value of rows third cell value by getting the prop3 values from the ObjectB. But it does not allow me to do so.
Error is of Type casting to ObjectB to string value. How do I handle this?
Hi,
The grid can't walk down into Object B and promote it's properties to columns. What will happen here is that your grid will show three columns: Prop1, Prop2, and Object B.
Since Object B is a class, the grid can't know how to edit it. It will display the cells of the column by calling the ToString method on Object B, but it can't know what to do if the user types into the cell. The grid has no way of taking a string that the user types in and converting it into an Object B instance.
There are a couple of ways you could deal with this.
The easiest way I can think of would be to use an unbound column. What you do is handle the grid's InitializeLayout event and hide the Object B column using the column's Hidden property. Then you add an unbound column to the grid for Prop3.
In the InitializeLayout event of the grid, you examine the value of the Object B column and get the Prop3 value and then set the value of the unbound column to that value.
Then in the AfterCellUpdate event, you trap for changes in the Prop3 (unbound) column and copy those changes into the Object B instance in the Object B cell in the same row.
I am working with the same type of issue Mike. When you say
Mike Saltzman"] In the InitializeLayout event of the grid, you examine the value of the Object B column and get the Prop3 value and then set the value of the unbound column to that value.
How exactly does one go about this? In the InitializeLayout event how do you examine the value of the Object B - get the property value you want and set that value to the unbound column.
I was doing this in the InitalizeRow event but it has caused major performance issues even after following your recommendations in the WinGrid Performance Guide. So in seeing this post, I was going to try it in the IntializeLayout event but am having difficulty finding the right syntax.
My thanks in advance for any help provided
nodak said:How exactly does one go about this? In the InitializeLayout event how do you examine the value of the Object B - get the property value you want and set that value to the unbound column.
This should be fairly simple and I can't see why it would cause any performance difference at all, unless you have a really huge number of rows.
The ObjectB column will be hidden (in InitializeLayout), but it's still there. So to get the value you just reference it like you would any other cell. You will need to cast it to the appropriate type, of course, and you probably want to check for null. So... the code might look something like this:
ObjectB objectB = e.Row.GetCellValue("ObjectB") as ObjectB;
if (objectB != null)
e.Row.Cells["Prop3"].Value = objectB.Prop3;
else
e.Row.Cells["Prop3"].Value = null;
I have submitted a new Feature Request :
Deep DataBinding (selectively generated columns, also from nested objects)
Hi Jabor,
Okay, I understand, now. Yes, everything you are saying here is correct. That's the way DataBinding in Winforms works. When a property of Object B changes, it sends a notification. Since you are re-directing that property so that it appears to be a property on Object A, Object A needs to fire a notification, as well.
Actually, as far as the grid is concerned, Object B doesn't even exist, so really the grid only cares about the notification on Object A.
As for the Panel and TextBox - you could do the same thing in the grid, as well. The difference is that the grid would show Object B as a child row and you have altered the structure so that it displays on the parent row.
I suppose, in theory, we could add a feature to the grid where it re-organizes the data at the grid level instead of on the data source level so that child properties appear in the parent row. That seems to be what you are asking for. But there is no such feature currently. You should Submit a Feature Request and perhaps this can be added in the future.
In the example above, if the classes A and B implements INotifyPropertyChanged, they fire the PropertyChangedEvent each time a property changes. If I use an IBindingList<A>, it only listens to the PropertyChangedEventHandler of the objects A. That means: 1.) the object A have to listen to the PropertyChangedEventHandler of the nested object B, and each time Prop3 changes it should fire PropertyChanged(“Prop3”) too.2.) if the nested object B (property “ObjectB”) of the object A changes, object A should fire two notifications:PropertyChanged(“ObjectB”) and PropertyChanged(“Prop3”), because all linked properties depending on object B changes too.
It is annoying. If I have a Panel and I drop a TextBox for Prop3 to it, I can set the DataSource to object A and DataMember to “ObjectB.Prop3”, and I do not need the things above.
I'm not sure what you are asking.
If you have a DataSource, and you implement ITypedList, it's your responsibility to send the appropriate notifications from the data source when something changes, if the data source does not already do so.
I don't know what PropertyChangedEvents you are referring to. Your data source needs to send a notification via IBindingList.