Hi!
I'm using an UltraComboEditor that uses Data Binding to get an Id out of an underlying business object which is used to select appropriate item from the items list. If another item is selected in the combo the Id is changed in the business object via the data binding which is fine.
I handle the ValueChanged event of the UltraComboEditor since I have to update another property 'Name' on same business object. This business object implements the INotifyPropertyChanged interface i.e. when 'Name' is set event OnPropertyChanged("Name") is fired causing data binding to fetch all visible properties again. This causes also the UltraComboEditor to display the item associated with the Id from the business object which is the original one thus the selection can never be changed.
I found a solution which works but my feeling is that it is more a workaround. In the ValueChanged event handler of the UltraComboEditor I explicitely set the 'Id' before setting 'Name' I. What I don't like on this solution is that 'Id' is updated again through the data binding.
Comments are welcome, Wolfgang
Hi Wolfgang,
It's a little hard to understand what's going on here. But it sounds to me like you are binding the list and the Value property of the Combo to the same table. This is logically contradictory and you should not do that.
A ComboBox control is unusual in that it can be bound two ways. You can bind the list and you can also bind the Value. Typically, you would bind to list to a list of options. For example, a list of U.S. States. And then you would bind the Value to a state field in a table of addresses.
If you bound the value to the same list of states that the list is displaying, then selecting an item from the combo would be changing the values on the list. In other words, if you selected New York, and then selected California, you would be changing the New York item on the list to now be California and you end up with 2 California's and no New York.
Maybe I am misunderstanding what you are doing, though.
Hi Mike,
thanks for your instant reply and sorry for writing my entry that unclear. I'll use your example with the U.S. states to illustrate my problem little better.
Let's say that I've a class U.S. State that contains following properties:
I've another class that represents some kind of address having following properties:
I'm doing the databinding to the UltraComboEditor so that the DataSource will be a list of U.S. State objects. The DisplayMember of the UltraComboEditor is set to Name, the ValueMember to StateId. The Value of the DataBindings will be set to StateId of the address binding source.
This works fine and every time I select a different state Name in the combo editor data binding mechanism takes care that the appropriate StateId will be set in the address object.
I also want to set the Capital in the address object whenever a new state is selected so I subscribed for the ValueChanged event of UltraComboEditor, get the ListObject of selected item in the combo which is in fact the selected U.S. State object, fetch the Capital property from it and set the Capital property in the Address object. Now the address object fires OnPropertyChanged("Capital") causing the StateId of the address object to be fetched again to select the U.S. state associated with that StateId so the State in the Combo cannot be changed since it always has the StateId from the Address object.
I've overcome that problem by explicitely setting the StateId property in Address object in the event handler for ValueChanged before setting property Capital and that works fine but I annul the data binding mechanism and that's what I don't like.
Alternativelly instead of subscribing for the ValueChanged event of the UltraComboEditor I could subscribe for the StateIdChanged event from the Address object . This event will be fired when the StateId is updated i.e. when UltraComboEditor looses the focus. Since I'm displaying Capital in a text box I want to see the capital of the newly selected state immediately in the text box, not to have to change the focus to another control. That is imho not quite intuitive from the user's perspective.
Hope that makes it much more clearer.
Kind regards, Wolfgang
Okay, I think I understand the issue now.
My first question is... why have a Capital field on the Address table? This seems like an unnecessary duplication of data. The Address table already has a state id, and it can look up the capital based on that StateId, so having the Capital as a field in the Address doesn't really make sense and makes more work for you, because now you have to keep the two fields in synch.
I don't see any other solutions besides the ones you list here. Your second solution, while less intuitive to the user, seems like the safer one from a coding perspective, since it handles any time the address field is updated, not just through the Combo. If you application is updated in the future and a second method is provided which allows changing the StateId, the developer will have to know to also update the Capital at the same time. And again, this is another argument for not storing duplicate data.
Thanks for your reply. You are totally right that the Capital is duplicated data on the Address and from the data model point of view it is redundant but there is at least one reason why we do that. The list of Address objects is shown in a UltraGrid and one column shown there is the Capital. Beneath the UltraGrid there is the UltraComboEditor to select the U.S. state that should also change the Capital name for the activated Address in the UltraGrid. The easiest way to achieve that is to add a property Capital to the Address class and whenever a new State is selected in the combo the new Capital value is displayed in the UltraGrid. I'm not storing that into database, it's just for the purpose of displaying it in the UltraGrid. If you know a better solution for updating the data in the UltraGrid without adding the Capital property to the Address class maybe you can share that information?
Another purpose, that is feasible in our project, is that we have to store some kind of snapshot. If the Address object is related to a customer's order you want to store the Capital name that was valid at that time when he made the order. Let's say a customer from California makes an order so we would store 'Sacramento' as the Capital. If over time Gouverneur Arnold Schwarzenegger decides that 'San Diego' is the new Capital of California, updates the State data for California appropriately we still would have 'Sacramento' on the Address object for that customer's order taken some time ago. Of course it's rather unlikely that something happen with a state's capital :-) but if you think on a list of company names presented in the Combo it's very likely that a company's name changes over time and due to e.g. legal reasons you have to store the company's name from the time when an order has been taken into the Address object.
qbupoew said:The easiest way to achieve that is to add a property Capital to the Address class and whenever a new State is selected in the combo the new Capital value is displayed in the UltraGrid. I'm not storing that into database, it's just for the purpose of displaying it in the UltraGrid. If you know a better solution for updating the data in the UltraGrid without adding the Capital property to the Address class maybe you can share that information?
A better way would be to add an unbound column to the grid. that way the extra field does not exist in the data source, only in the grid, and this would avoid the whole problem you are having.
qbupoew said:Another purpose, that is feasible in our project, is that we have to store some kind of snapshot. If the Address object is related to a customer's order you want to store the Capital name that was valid at that time when he made the order. Let's say a customer from California makes an order so we would store 'Sacramento' as the Capital. If over time Gouverneur Arnold Schwarzenegger decides that 'San Diego' is the new Capital of California, updates the State data for California appropriately we still would have 'Sacramento' on the Address object for that customer's order taken some time ago. Of course it's rather unlikely that something happen with a state's capital :-) but if you think on a list of company names presented in the Combo it's very likely that a company's name changes over time and due to e.g. legal reasons you have to store the company's name from the time when an order has been taken into the Address object.
I guess I can kinda see how that might be useful. In such a case, though, it would probably be better to add a new State entry for the same state with a different capital and use the new one going forward so no data is lost. But since you are not storing the information in the database, anyway, I assume you are just talking theoretically here.