I have simple details-edit form.
Data is read from Database. DataAdapter fills DataTable and Dataset
I have created BindingSource (bs) and bound all controls to bs
Before saving to database bs.EndEdit() is called (in order to reflect all changed controls values in datasource)
All works great, except scenario when there are errors caused by constraints (eg column cant be NULL, or unique value is expected).
In this case bs.EndEdit() causes exception (what is OK) but also revert all changes (what is not OK to me...). So I end up in the situation when Im loosing all data entered by user (giving no chance to fix problem)
I must be doing something wrong - can someone please advise how to properly handle such scenarios?
In order for this to work, the BindingSource's underlying data object must implement IEditableObject:
Ref MSDN #1:
When the EndEdit method is called, all pending changes are applied to
the underlying data source.
This method has no effect unless the objects contained by the data
source implement the IEditableObject interface.
Ref MSDN #2:
IEditableObject Interface Definition Namespace: System.ComponentModel
Assembly: System.ComponentModel.dll Provides functionality to commit
or rollback changes to an object that is used as a data source.
Cheers
Related
I have binded my customer name textbox to Customer Model and set the mode to two way now I want to update the edited name to database. How can I achieve this ?
Your question is very vague as it doesn't say whether you wanted this on PropertyChanged or when you have a button with either Click event handling or ICommand binding on it.
The decision when to update is totally down to the business model that you are applying. Generally speaking, it's never a good idea to update directly from a PropertyChanged event because it might be a temporary edit and you may wish to update against.
For example, if you have UpdateSourceTrigger=PropertyChanged, then as soon as a character is type, the Property is updated with the new value and if you implmented iNotifyPropertyChanged events, that would instantly fire an update to your database. Because a database connection is transient, usually over a network, it may or may not be available, and it may or may not timeout during a partial update. Thus, you could end up locking up your code or if multi-threading, causing race conditions.
Therefore, it's always better to implement the changes via a save button or when the screen is closed/navigated away from (such as what iOS/Android do).
I use Entity Framework. When I bind an entity set to a standard DataGridView control I lose sort-by-click-on-header functionality. I even tried to bind the entity set to a binding source first but results are the same.
Also if I try to sort a column from code I even get an exception that an interface is not implemented... Are standard EF classes un-sortable (would be a bummer)? Needless to say, sorting works if a DataView is provided as data source.
How could I get around this problem? Thanks.
Late to the party but thought I'd at least post an answer... There are two ways to achieve this with little fuss (actually the same method, just slightly different route).
So we have a basic EF context query, pre-execution.
var query = context.Projects
.Where(x => x.Division == selectedDivision);
Load the query so entities are in the local cache. Then point the DGV's binding source to the Local cache's synced BindingList
query.Load();
projectBindingSource.DataSource = context.Projects.Local.ToBindingList();
OR... There were times when I didn't want/need change tracking or the cache "got in the way" of other operations so I needed a non-tracked collection.
Execute the query without tracking and load it's result into an ObservableCollection (Which is what .Local is). Point the DGV's binding source to the ObservableCollection's synced BindingList
var locs = new ObservableCollection<Location>(query.AsNoTracking().ToList());
locationBindingSource.DataSource = locs.ToBindingList();
All text, numeric, and bool columns will have sort enable for header-click. What won't sort are columns for Navigation Properties: Say a Project has an Owner navigation property, since I have Owner entity's ToString() override display the Owner.FullName property I will see an Owner column with the FullName value but I assume the sorter still sees the column's type as the System.Data.Entity object (instead of the bubble up text that is displayed) so doesn't have a default sorter for it.
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.
I have a Microsoft Access form that is bound to a linked SQL Server table that has a computed column. I have a control bound to the computed column.
I already realize that the computed field cannot be refreshed until AFTER a record is saved. Beyond that, what is the best way to refresh that textbox that is bound to the computed column after save.
I would prefer not to do a me.requery (a requery of the whole recordset).
Is there a way to JUST refresh that one field?
EDITED FOR CLARITY: There are actually a few strategies to consider.
Form.Refresh() will refresh your Form's recordsource capturing modifications and deletions to existing records and will stay positioned on the current record. However, you would not see any NEW records that were added since you opened your form.
Form.Requery() will re-run the Form's recordsource query. You will see all the Form.Refresh() changes AND it will show you any new records. On the UI, Form.Requery() repositions to the first record.
Form.Control.Requery() is similar to Form.Refresh() in that you will not change record position or see NEW records. It will update your control, assuming the control is based on a query/table.
You'll need to be sure that the triggering event involves a database update. There can be cases where the control's AfterUpdate() precedes database I/O, which wouldn't help you.
Thanks guys. Here it what worked.
In the Form AfterUpdate event I did a Me.ControlName.Requery. This was perfect as it did not do a complete form refresh or requery.
I just experimented with different event/method combinations until I got the best result.
Thanks for the input.
Seth
2016 (related) Answer: In Access 2016, I have a control that is a calculated field based on values in 4 other bound textboxes. I set the Control Source for the calculated field to be =gsngCalculatePaymentAmount([txtInterestRate],[txtLengthOfLoanInYears],[txtSalePrice],[txtMoneyDown]).
But I needed the value to be refreshed whenever ANY of the values for any of those 4 textboxes changed. Had difficulty in making the calculated value refresh. SOLUTION: In the AfterUpdate event in EACH of the 4 textboxes whose value was being used for the calculated field, I simply did the following:
Dim v1 As Variant
v1 = Me.txtMyCalculatedTextbox
Simply referencing the value of the calculated field resolved it!
Rex
Have you tried .Refresh for either the underlying recordset, or for the bound control? I would expect it to work for a Jet/ACE back end, but the interaction with different database server back ends is going to be non-predictable.
There might also be an interaction with you ODBC refresh interval, but I would expect a manual refresh in code to take care of that.
Where to call it is another issue -- I would assume the appropriate place would be in the AfterUpdate events of the controls bound to the fields the calculation is based on. But you might have to save the record for the server-side calculation to happen -- Refresh alone might or might not do the trick. I know with Jet/ACE data sources a Refresh saves the record, but I don't know for certain if it behaves the same way with ODBC data sources.
I did it this way (the control source of txtTextBox is an SQL Server field whose value is computed):
On Error Goto ErrorHandler
'After saving data when I wanted to see the updated value of computed field
txtTextBox = txtTextBox & ""
ErrorHandler: If err.Number = -2147352567 Then 'The data has been changed.
Resume Next
else
msgbox err.description
end if
I have the following situation: I built an Access form with a subform (which records are linked to the records of main form via certain key). When I try to delete any record in the subform, I get the following message: “Access has suspended the action because you and another user tried to change the data” (approximate translation from German). Does anyone know how to delete those records from the subform (and, respectively, from the table behind the form).
If you are currently 'editing' the current form then it will not allow the action. Editing a record can sometimes be triggered by simply clicking inside a field, or other simple actions you wouldn't normally consider 'editing'.
This is usually avoided in Access by using the RunCommand method to undo any edits before deleting the record:
DoCmd.RunCommand acCmdUndo
samjudson suggested:
DoCmd.RunCommand acCmdUndo
You can also use Me.Undo, to undo the last edit to the form in which the code runs.
Or, Me!MySubForm.Form.Undo to undo the last unsaved edit in the subform whose subform control is named "MySubForm".
You can also use Me!MyControl.Undo to cancel the last edit to a particular control.
"DoCmd.RunCommand acCmdUndo" will apply the Undo operation to the currently selected object, but you won't know for sure whether it will apply at the control or form level. Using the commands I suggested completely disambiguates what gets undone.
Keep in mind, though, that Undo will not undo edits to a control after the control's AfterUpdate event has fired, or to a form after its AfterUpdate event has fired (i.e., the data has been saved to the underlying data table).
Also check the "row locking mechanism" that you have. I haven't used Access in a while but I remember that you could use set that in the table properties. You can access those properties clicking in the famous "dot" in the upper left corner of the table to bring up its properties. Well if you're using Access, you know what I'm talking about.