Hi,
I'm looking to bind an ultragrid to a dynamic datasource. The source of my data is found in a list of "prices" objects, which have Properties holding the numbers I want displayed.
It would work perfectly to create an object MyDataRow which would encapsulate some of the "prices" objects, and expose one property for each column.
That way I could use a BindingList of MyDataRow objects, and each column would be nicely bound to the UltraGrid, with a proper INotifyPropertyChanged implementation to insure the grid refreshes when my underying "prices" change.
However, one of my constraints is that I need to dynamically add columns at run time. That seems to be a problem.
Indeed, since on this architecture a column is necessarily a Property of the MyDataRow object, I cannot dynamically modify the class to add Properties, and then fill all the existing instances...
How can I get around this problem, and properly have BOTH Databinding to object properties AND dynamic column creation in an ultragrid?
I'm not entirely sure I understand what you are trying to do.How do you intend to make your prices object vary it's own properties? Even without considering the grid or data binding, there is no way to do this. So how do you intend to define your data structure and add properties to it?
So I don't see any way to do this using a custom-defined object like a "Prices" object that you create yourself.
It sounds to me like what you need is to use some other data source which has the ability to dynamically add and remove columns. A DataTable/DataSet has this ability, as does the UltraDataSource component.
Actually.... what I said above is not really true. There is a way to have an object that dynmically adds and removes bound columns to itself. Obviously there is, since Datatable, DataSet, and UltraDataSource do it. They way they do this is by implementing IBindingList and ITypedList. But it doesn't make a lot of sense for you to re-invent the wheel here when there are perfectly good objects already in place that will do this for you.
My advice would be to use an UltraDataSource, since it seems like you have a pretty simple set of data here without any hierarchy and without dynamically-changing relationships.
Hi Mike,
My prices objects will not update their properties themselves, they are living inside a big dictionary, and are updated by other classes browing this dictionary and modifying them independantly.
Therefore the Data grid is a read-only display of those prices, but it needs to manage databinding, so that when a price moves (by the action of an outside class), the grid displays instantly the new values.
To be clear, here is an example of what it may look like:
A "Price" class has a "Value" property of type "double", and I have a List<Price> living somewhere, holding all my prices.
Then I have a "MyDataRow" object, which has several properties of type "Price". like "MidPrice", "HiPrice", and "LoPrice" for example. MyDataRow also needs to implement INotifyPropertyChanged, to support databinding.
As I fill the MyDataRow objects, I take Price objects from my List of Prices.
I then place the MyDataRow objects in a BindingList<MyDataRow>, and use it as the datasource for the ultragrid.
This will display a column for each Property of the MyDataRow object: a MidPrice Column, a HiPrice column, and a LoPrice column. And if MyDataRow correctly propagates the NotifyPropertyChanged events caught from its Price objects, they will be correctly refreshed on the grid.
The problem with this very standard solution, is that I cannot add a new column at run time (let's say "AveragePrice"), and fill it with new prices objects, that will be displayed in the grid. A new column requires a new property of the MyDataRow object, which I obviously can't create in the class at run time, let alone populate its value for all the existing instances of MyDataRow already in the grid.
The alternative, as you mention, is to use a DataTable, or an UltraDataSource, but my understanding is that those sources only allow me to place simple type objects (double, string, etc..) in them, and therefore I can't have my "Price" objects live in them. And even if I choose to have columns of type "system.object", all they will do to display my "Price", is call the "ToString()" method, but they will not display the "Value" property, nor will they manage databinding to display a new value when the prices change.
In sum, it looks like BindingSource will allow a great databinding with my underlying objects but won't be flexible enough to add columns on the fly at runtime;
whereas the DataTable/UltraDataSource would be flexible and would easily add columns, but won't allow proper databinding with my Price objects.
Is my dilemma clearer in those terms?
Do you see a way out of my dilemma?