I have form in which I can change the name of stations in my database (SQL Server: in table Stations).
To choose which station I want to edit I've used a combobox.
What I want to happen now is that when I update a station, my ComboBox with stations immediatly gets updated with the edited station.
Is there a way to do this or is this impossible?
I am assuming that this is a Windows Forms application based on the subject. If this is the case, then you have most likely performed databinding, perhaps using a DataTable or a collection, to the ComboBox.
If this is the case, and the object that you have databound supports System.ComponentModel.IBindingList, then all you need to do is add or update the record in the underlying object.
When this happens, the object that has implemented IBindingList sends a message out to any controls that are "listening" and tells them what just happened. The control will then update their data/user interface to reflect these changes.
Related
I have a .NET 2.0 Winforms app (and Subsonic 2.2), where I have a DataGridView and few controls in a panel, both are bound to a BindingSource whose datasource is a Subsonic ActiveRecord collection. When a user selects a row in grid, the corresponding details are shown in the panel below in appropriate controls (texbox, combo, datetimepicker, etc.)
When a user changes some data, and tries to move to some other row, I want the app to display a warning that data has changed and it needs to be saved. If user selects yes, the data should be persisted.
I face a few issues:
a) In the DGV.RowEnter event handler, I try to find if the current row is dirty (using IsDirty of activerecord). If so, I display a messagebox.
b) When I save and rebind the grid, the datasource of the datagridview cannot be re-bound to a new (saved) collection. The app throws error that 'operation is invalid'.
c) Also, since both the gridview and controls are bound to same collection, whenever I change something in the control, it is reflected in grid, but when user selects 'No' to save data, the changes should be undone. Does subonic has any Accept / Cancel changes like a dataset?
Thanks!
I finally figured it out:
a) While I am able to save data without any issues, the app throws error only when I try to "rebind" it. As the grid and controls are already bound to datasource, which contains latest changes, I removed the rebinding code and now it no longer throws any error ("Operation is invalid"
b) Undoing changes - this was accomplished by calling BindingSource.CancelEdit() when user does not want to save changes.
I created a new entity object and bound it to controls in another window (edit window). After modifying and saving I assigned a new entity object into the one in the main window. The old entity object is bound into a datagrid, now I want the datagrid to display the data that I had modified and saved.
ObjectContext.Refresh Method (RefreshMode, Object) seems to be what I want but I don't know how to use it correctly.
In short :
I have a main window with datagrid displaying the whole data of the table. Users can pick one row and edit it in a edit window. After saving, the datagrid should display what has been modified.
Your best bet here is to use an ObservableCollection as your data source for the datagrid instead of the query.
And look at implementing INotifyPropertyChanged interface in your Customer class.
The ObservableCollection is initially populated by the database query. User changes are made to elements within the ObservableCollection and once complete you then just need to trigger transferring the changes to wherever you originally obtained your list of Customer objects
By doing this changes made both to the collection of Customers and to individual Customer objects (if present within the datagrid) will be automatically updated for you.
edit
I must admit that I'm a bit rushed to offer up any code at the moment, but here's a pretty good article that explains how to use ObservableCollections and classes that implement INotifyPropertyChanged. It also has code examples, which although in VB.NET should give you enough of an idea to get started.
In effect you separate your code into distinct layers UI (View), business logic (View Model) and data layer (Model where your entity framework resides).
You bnd your datagrid to the ObservableCollection type property in your Customers class and your edit csutomer window is bound to as instance of your Customer class.
I have simple SL user control. A listbox which shows all customers and on the right a number of textboxes and comboboxes that are bound to the SelectedItem (Customer) in the listbox. The SelectedItem bound to SelectedCustomer property.
I am looking for a pattern/methodology to deal with canceling changes made to the customer (in the bound textboxes and combo boxes).
The edit controls (textboxes and combo's) can be one or two way bound to the selecteditem of the listbox.
If they are two way bound, immediate changes in the textboxes are reflected in the listbox. If they are oneway bound the changes in the textboxes are not reflected in the SelectedCustomer object.
At the bottom of the edit form i have typical Save, Cancel, Delete buttons. The save button for instance would take the SelectedCustomer object (if twoway bound and I would send through service for saving on server).
If the textboxes are one way bound i have to capture somehow the textbox values and insert into some object for sending to the server for saving.
If I use twoway binding , and say the save operation fails...i have to set the SelectedCustomer values back to original values otherwise the client now continues to see data that has not been saved.
There must be an easy way of dealing with this type of scenario....
RIA Services with Entity Framework already provides this functionality, basically how RIA services works and you can do it too as follow.
Each class implements interface called IEditableObject, which provides methods BeginEdit/EndEdit and CancelEdit. And it also stores (copies) instance of same class with name "OriginalEntity" with same values that were loaded from server.
After the form shows up for user to modify, BeginEdit is called, which probably caches every property using reflection, in some sort of dictionary. If you call CancelEdit, then values from OriginalEntity are loaded back in object.
Upon some errors while saving changes, you can either refresh the entities from server (best way) or you can try loading properties back from OringalEntity property.
I wouldn't discard user changes, as that easily leads to user frustration. IMHO, the user should not be informed about connection problems by uncontrolled data rollbacks.
I've got a Silverlight application that has created a master/detail view of data coming from an OData feed (my first app). When I make changes to an item in the detail view, they are showing up just fine in the master, but the user has no indication on what has changed (including adds & deletes).
For some reason I can't find a property that indicates that the collection has changed. There is a CollectionChanged event, but that's only for items it seems, not for their properties.
Is it possible to easily determine what items have changed in a DataServiceCollection and easily show which ones those are? I expect I could build something that walked through the collection, but that's not idea.
There is INotifyPropertyChanged event, that gets fired when the properties are changed. Does that help?
Thanks
Pratik
I can't believe I haven't run into this issue before: I have a data bound form and before the user navigates to another record I want to save some additional data from non-bound controls in addition to the bound data. The only event I can find is BindingManagerBase.PositionChanged but this seems to happen after the current record has changed.
Is there a way to get an event when the data has just been saved but before the binding has moved to the new record?
Have you looked at implementing a ListChangedEventHandler to detect when your list changes? The list seems to raise an event of type Reset when the list position changes (assuming your data is in a BindingList<>).