I'm having a bit an issue wrapping my head around this for whatever reason.I have an UltraGrid with data bound like so: UltraGrid.SetDataBinding( IBindingList<T>)
Later, I added an UltraCombo (because I like the flexibility of its appearance) but I've run into issues with the ListChanged events not firing properly. I stepped into the UltraGrid_CellChanged event and can see that the value of my grid cell hasn't changed at all, even though its display text has.
My question simply, I suppose - Which object can I bind to a grid column that supports IBindingList and ListChanged events but also has the appearance capabilities of the UltraCombo?
Thanks.
Hello ,
When you are create a BindingList<T> and you want ListChange event to be fired when you change a property of T class, then you should implement INotifyPropertyChanged Interface to your T class. Aftet that bind this BindingList<T> to the UltraGrid and change the value of some cell, then the ListChange would fire. More about INotifyPropertyChanged Interface you could find here:
http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged.aspx
Also I am attaching a small sample where I have a class Patient, which implements INotifyPropertyChanged Interface and when you change the value of some cell and leave this cell (in order to commit changes) you will get a message from ListChange event.
Please let me know if you have any further questions related to Infragistics.
Hi,
I have reviewed your solution. I may have been misleading in my initial question, so here it is again with a little more information. I am using UltraCombo.SetDataBinding(BindingList<T>) where my binding list does in fact implement INotifyPropertyChanged. The debugger throws a NotSupportedException: "The list must be an IBindingList to AddNew."At this point I'm not sure why I am getting this error. My first thought was that maybe the UltraCombo did not support ListChanged, however your solution proves that it does.
I am able to bypass this exception and allow the UltraCombo to bind anyway. The behaviour I am seeing however, is that ListChanged events will be thrown, but will not update the T class. The ValueMember field remains constant and the DisplayMember will change text in the cell. Further, another issue I am seeing is my drop down is displaying the ValueMember instead of the DisplayMember. (I am seeing integers in my UltraCombo.)
Do you have any ideas on how to resolve this?
If you are binding to a BindingList<T> then you should never see an exception like that, since the BindingList obviously does support IBindingList.
Can you post the call stack of the exception?
Sure thing
.
This screen shot isn't really very helpful, because I can't see the whole call stack.
What exactly are you using for your DataSource? Are you using IBindinglist<T> or BindingList<T> or IList<T> or List<T>. Are you using your own custom class derived from one of these classes?
Just to be clear... the grid doesn't fire any ListChanged notifications. The grid updates the DataSource and the data source should be calling these methods. The grid just listens to them.
So if your data source isn't firing ListChanged notifications, then it seems like there is a problem with your data source.The grid works just fine with BindingList<T>, DataSets, DataTable, and UltraDataSource. So if you are creating your own custom data source class and implementing an interface and something isn't working right, it's probably because your implementation is incorrect or incomplete.
The error message you are getting here indicates that the DataSource you are binding to is an IList and not an IBindingList. IList doesn't support adding new rows of data, so it's not a good choice for a data source. IBindingList is much more robust and does support adding new rows of data, but there may be other limitations. For example, if you are using BindingList<T> and your class (T) does not have a public parameterless constructor, then the BindingList will be unable to add new items to the list, since it cannot know what to pass in to the constructor.
I cannot modify your sample project to reproduce the error. I have tried and was unsuccessful.I am setting the DataSource to a BindingList<T> where T is a custom class which implements INotifyPropertyChanged. (And as mentioned has a default 'ctor'). T also has BindingLists included in its properties to set up hierarchical grid views. (I tested to see if this is what is causing the problem, and it doesn't seem to be.) Here's a screenshot of the full Call Stack, sorry, forgot to scroll up the first time around.
"So if your data source isn't firing ListChanged notifications, then it seems like there is a problem with your data source."
I have several columns with UltraCombos in them, and they will all fire ListChanged events. Only the column with an UltraCombo with a DataSource of a BindingList<T> does not fire this event. Hopefully this is enough information.
Hey Mike,Just getting my properties mixed up I suppose. I meant DataMember, which I still don't understand how that is meant to work. I changed this to ValueMember and all is well. After viewing the Call Stack and noticing that the system was trying to convert the string to an integer this became quite apparent.
Anyway, thank you so much for your help. It has been invaluable as always.See ya next time I get a headache.
Cheers.
If you are seeing the DataValue instead of the DisplayMember, then this usually indicates a problem with the DataTypes.
You have to make sure that the values in the ValueMember column of the dropdown are the same DataType as the values in the grid cells.
rzabransky said:with the UltraCombo set as the EditorComponent of a column
This is not a problem and should work, but it's not the most efficient way to provide a dropdown list in a cell. Unless you are using multi-select, or EditorButtons, or a DataFilter you are better off using the UltraDropDown control as the ValueList of the column.
But since you are assigning an EditorComponent to the column, make sure you are not also assigning a ValueList to the same column. That could also cause a problem like you describe.
Hey Mike,
Thanks for the information. It is quite useful. I have rechecked my properties and found no ILists. I did find a few properties which may be suspects, such as one band containing two IBindingLists (where an Inventory can have both Clients and Tickets). Alternatively I have an UltraGridRow property so that my ListObjects point back to their row. I'm not sure if these are cause for concern, since I haven't tested them.
I decided it best to remove the IBindingList from my UltraCombo because you mentioned the exception may be caused by the child data already being in a relationship (which I believe it is). This resolved numerous exceptions that were causing performance hits on the program.
Instead, I am now binding my UltraCombo to a simpler DataTable. However, I am still having problems with the DataValue/DisplayMember not being displayed properly. It seems I still cannot change the value of the column through the drop down or other means, and when forcing a commit on the cell the display text is removed and the data value is shown.
As such: The Data Value ex) 5 is always shown over the display member ex) RZabransky. When switching to RZabransky2 the data value will remain at 5.
I have never seen this behaviour before, and frankly I'm at a loss as to how this could happen. Additional information which may or may not be relevant is that the UltraGrid is displayed in a dialog with the UltraCombo set as the EditorComponent of a column. When attempting to change the value of that column their are numerous FormatExceptions, which are actually typical when using ShowDialog() so I didn't pay much attention to them.
Thanks again.
Okay, this call stack indicates that the exception is occurring when you set the DataSource property on an UltraGridBase. So this could be an UltraGrid, UltraCombo, or UltraDropDown. I think you are saying it's an UltraCombo.Is that right?
The actual exception is occurring when the CurrencyManager in DotNet is trying to add a new row to the data source. This is not something the grid does. It happens when the grid asks the CurrencyManager for the data structure so that it can create the columns and bands to display the data. When the CurrencyManager encounter a field in the root table that should be represented as a list, it tries to get the data structure of the child data. If it cannot get it from the property type, what it does is it tries to add a new row to the child rows collection of the first parent row. It then uses the child row to determine the structure and then cancels it.
So my guess is that you are binding the combo to a hierarchical data source and one of the fields in the data source is an IList and not an IBindingList. I know you said that this is not the case, but it's the only way I know of that you get that exception. Perhaps there is some other reason that it is happening in this particular case - maybe there is some other type that causes the same Exception.
I recommend that you examine the fields in the data source you are using for the combo very carefully and make absolutely sure that there are no public properties which return a type which implements IList and not IBindingList.
Another possibility is that the data you are binding to is already a set of child data in a relationship. In fact, judging by the DataMember you are using here (Inventories.Clients.Tickets) that looks like it may be the case. In that case, if there is currently no data in the table, the same thing will happen - the UltraCombo will be unable to determine the data structure without adding a row. And it may be that the CurrencyManager cannot create a new row in this case, because it doesn't have enough context in terms of the parents rows.
Another thing you might want to try, just as a test, is to bind the same DataSource to some other controls. For example, you could bind an UltraWinGrid, a DataGridView, or ComboBox to the same data, just to see what happens. I expect you will get the same exception in all cases.