I have Animal class and derived Cat class
: Class Animal
{
Public String Name{ get; set;}
}
Class Cat : Animal
Public string FurColor {get; set;}
Now I have ItemCollection<Animal> animals = new ItemCollection<Animal>(); with a few animal objects. Then I call UltraGrid1.DataSource = animals. The grid correctly shows the columns for the Animal properties.
If I populated the animal collection with a few cat objects. The grid only shows the properties of animal. No cat properties are shown as column of UltraGrid.
If I declare ItemCollection<Cat> cats and set grid data source as cats. The cat properties will be shown in the UltraGrid columns.
In WCF DataContractSerializer I can declare Cat as KnowType of Animal to get collection of anima l correctly recognized as cat. I s there a similar way for the UltraGrid to show the actual data type properties instead of only the base type.
No, I don't believe the WinGrid can support this. There are two problems with this:
I could be wrong about #2, though. And if so, you might be able to acheive what you want by using the WinTree instead of the WinGrid. The WinTree has a ViewStyle called FreeForm, in which you can display non-homogeneous data. But I think you would have to generate the ColumnSets for each possible type and assign them to the nodes yourself - probably in the InitializeDataNode event.
Hi Mike,
The user control is designed to be generic to all animals. So I declare the collection as ItemCollection<animal> _animal. But each time only one type of anumal. therefore data is homogeneous. I populated the _animal with cat objects. In debug I checked the ultraGrid DataSource, it has the right data. The grid should be smart enough to display the derived properties as its columns. There must be a way to do this.
Julie
Hi Julie,
As I said, there's no way to do this. The grid cannot show non-homogenous data. All of the rows in the band must have the same columns. So if your Cat class derives from Animal and has extra properties you want to show just for those row, it will not work.
Hi,
I'm not sure I follow you.
The grid gets the data from the BindingManager in DotNet. The grid's DataSource needs to support IBindingList or IList in order to function at all - although IBindingList is much more robust. Using an IList will provide limited functionality in the grid.
Anyway, If it works when you use ToList, then my guess is that whatever data source you were using before (without ToList) did not implement the proper interfaces such that the BindingManager in DotNet could get the data structure.
I have the same problem, and actually, this works if you cast your list to a list of objects (using linq: catsThatAreAnimals.Cast<object>().ToList()) before you bind it. I can't see why and it bugs me big time. The declared type is object but still columns are bound to properties of the actual type you provide. Now this could be a list of different types of objects (havnt tried that though). How come this works?
If you have to only bind the grid you can serialize the List<Animal> and then put that into a Datatable and bind the datatable to the grid.
MemoryStream stream = new MemoryStream();
XmlSerializer serializer = new XmlSerializer(typeof(List<Animal>));
serializer.Serialize(stream, baseList);
stream.Position = 0;
DataSet set = new DataSet();
set.ReadXml(stream);
DataTable
test = set.Tables[0];
this.ultraGrid1.DataSource = test;
But you will no longer get the underlying ListObject as the Animal class.
zhililin said:Then I make the changes to the data, both base class property and derived property, after making the changes I checked the my cat’s collection, the cat’s collection property values are not changed as I expected. That means my data is not binded with the grid cells..
I'm not sure what this means. If you are making changes to the data and the data in the collection is not changed, then something is wrong with how you are changing it. That has nothing to do with the grid.
If you make changes directly to the data and the grid is not displaying those changes, then the data source is not notifying the grid of the change. This notification comes from the implementation of IBindingList, so if your data source implements this interface and it's still not working, then something is wrong with the implementation. If you data source does not implement IBindingList, then you either need to implement it, or else you will need to refresh the grid data by calling grid.Rows.Refresh(ReloadData) any time something in the data source changes.
zhililin said:In the load event I set data source to my Cat’s collection, (which is declared as ItemCollection<Animal>, therefore no derived properties are bind to the grid column). In the initialize event I add a cat’s property column to the ban 0 (I don’t know what you mean Unbound column).
To add an unbound column, you use the band.Columns.Add method.
zhililin said:In the InitializeRow event I get the ListObject. But I still have to cast the ListObject to Cat type before I can access the cat property. Event I can cast I cant not get colum info from InitializeRowEventArg. How do I populate the Unbound column data?
Yes, you will have to cast the ListObject to the appropriate type. There's no way around that.
To populate the unbound column, you simply set the Value on the cell. Something like this:
e.Row.Cells["CatFur"].Value = ((Cat)e.Row.ListObject).CatFur
Here is my affert
Looks like the BindingManager in .net only know the declared type instead of the actual type. Anyway I tried both of your options options.
Second option: use the virtual mode.
In the form load event I setup the columns like this:
this.ultraDataSource1.Band.Columns.Add("CatFur", typeof(string));
In the event ultraDataSource1_CellDataRequested I set the cell value using my cat’s collection. I was able to use the property info to set the cat’s data without knowing the derived type Cat. The ulta grid displayed the right info.
Then I make the changes to the data, both base class property and derived property, after making the changes I checked the my cat’s collection, the cat’s collection property values are not changed as I expected. That means my data is not binded with the grid cells..
I tried the first option add a Unbound column:
In the load event I set data source to my Cat’s collection, (which is declared as ItemCollection<Animal>, therefore no derived properties are bind to the grid column). In the initialize event I add a cat’s property column to the ban 0 (I don’t know what you mean Unbound column).
In the InitializeRow event I get the ListObject. But I still have to cast the ListObject to Cat type before I can access the cat property. Event I can cast I cant not get colum info from InitializeRowEventArg. How do I populate the Unbound column data?
The whole design of my user control is no need to know the derived types at the compile time and able to bind the data to the ultra grid data source at the run time with the derived data collection. More suggestions?