WPF "undo" with deep copy - c#

Current situation
I have a WPF application where I use MVVM and NHibernate. I have a master/detail window with a listbox with all my customers, and the selectedItem of the listbox is the object that is being used to display the customerdetails in the detailscreen.
In the detailscreen I have an add, edit, delete, save and an undo buttton. Everything works with the binding I've set up.
Problem
But for my undo button I was thinking of making a copy of the original Customer object so when I click the undo button the field will be resetted to the values from the original values. But in my customer object I have an Address object and with a shallow copy the 2 objects will keep the same reference to that object. So when I change a field from the Address object the original Customer address will also be changed. I was thinking of doing a deep copy of my Customer address but I can't make my object serializable (It's not in my control to change the Model objects)
Is there any way to do a deep copy without serialization?
Or is there some standard way to accomplish the behavior I want to achieve?

I would simply go back to the database and reload the customer object. That ensures that the data you're displaying is consistent with the data in the database and reduces the risk of concurrency issues.

Related

MVVM best practice - work directly on the reference from list members of the model or make a copy?

Assume I have a model which offers me a property, which is list of custom objects. The model is a singleton and I give the reference of this property to the ViewModel. These custom objects have for example boolean properties. Now the user changes these values by clicking in the view and operating on the references in the model. Thus the list in my model does not change and therefore the model can not notify other views unless I implement event handling for every list member.
On the other hand side my model notifies others if I assign a complete new list.
The question is: is it in general good idea to work on the references of my model or should every ViewModel make a deep copy of the list content and assign later a complete new list to the model. And if not should I add event handling for every member of the list in my model?
Btw. the ObservableCollection is no option because it does not detect item changes and I think a general model should use the Ilist interface.
There is no straighforward answer to your question, it is all a matter of how you want your application to behave.
If you want any changes made by the user to be immediately effective in the application, then you should work directly on the references returned by your model. But on the user hand, you have to handle the cases where the application has the initiative to make changes to the list and notify the user.
On the other hand, if you prefer that any modification made by the user has to be validated by the push of a "Apply changes" button, the option of cloning the list is probably the best choice.

How does validating and saving data in WPF MVVM work right?

I am new to MVVM (and a bit of WPF) and I've read many Code Project articles, blog posts and Stackoverflow questions in the last few days. I have the impression that data binding works really nice to display data once loaded from a data source (database) and to keep the model in sync with the view, also updating all other appearances of the model data in the view(s).
But I still have no real clue how saving, and before that validating, is supposed to work right. I have a strong Windows Forms and ADO.NET background. I am well familiar with coding both the database access layer and the view updating. Back then, you had temporary, scratch data, being edited, only in the view, and the last saved version of the data in the model classes and the database. The model classes were usually in sync with the database. It was the view that contained the data that was not saved yet.
You also had a Save button that would read all data from the controls, validate it in code and either accept and save it to the model and database, or not update the model and display an error message instead. In case of an error, the user input remained in the UI for the user to correct it. But no other part of the application could see it. And you had a Cancel button that would just throw away that part of the view that contains the editing controls - the model was still valid and unchanged.
Now with data binding and ViewModels just exposing data from the Model classes, what is entered in a TextBox immediately goes into the model, be it correct or not. IDataErrorInfo is nothing more than that - informational. You can regard it or ignore it. The only hard validation that is enforced is type conversion: you can never update a non-numeric string into a numeric model field. But that's about it. I'm going to solve that by letting the ViewModel do all validation and throw an exception from the property setter on invalid data. This is the only way to implement the known behaviour.
But where does saving and discarding of data go? When will I actually write data back to the database? Does every leaving of a TextBox cause a database write so that I won't need an explicit Save command anymore (and only get reverting through Undo)? When will I validate a whole record of data? How will I deal with the model and database being out of sync, with invalid input immediately propagating through the whole application and all views thanks to data binding? When and how can I discard any user input with a Cancel button, leaving the model unchanged - or reverting it to a state before that editor dialog was opened?
I feel like MVVM does not provide solutions to these elementary problems. Did I just miss them or do they really not exist? If MVVM is not a solution to this, then what is? Or should MVVM better not be used for data editing applications in WPF?
MVVM doesn't answer these problems for you - you have the flexibility (power? burden?) to resolve database writing in any fashion you choose. If you need to collect all the data before you save back to the database, you can do that - just add a Save button bound to a SaveCommand on the ViewModel, which executes your data access stored procedure/entity framework update method/whatever. If you want to record each bit of data individually, then you'll need to call the data access procedures somewhere else (probably the property setters on the view model?)
Essentially, MVVM is not a complete end-to-end software pattern. It is only looking at the communication between what the user sees (listboxes, textboxes and buttons) and the application itself. Your data access code, serialisation, storage, persistance, whatever you are using and however you are using it is all held behind the MVVM side of the application, in your application code (the model). You can write this however you like.
I'm currently writing an application where a user fills out a form and hits Save or Cancel. Save and Cancel are both buttons bound to commands on the ViewModel. In the ViewModel constructor, the properties of a model object are copied to the properties of the ViewModel. On Save, the properties of the ViewModel are copied back to the model's properties and the data access code is initiated. On Cancel, the model's properties are copied back over the ViewModel's properties.
class MyViewModel
{
public MyViewModel(MyModel model)
{
this.Name = model.Name;
this.Colour = model.Colour;
}
public string Name {get;set;}
public string Colour {get;set;}
// commands here that connect to the following methods
public void Save()
{
model.Name = this.Name;
model.Colour = this.Colour;
model.SaveToDatabase();
}
public void Cancel()
{
this.Name = model.Name;
this.Colour = model.Colour;
}
}
That's a simple way to do it - of course, you need to throw in INotifyPropertyChanged and the rest of it, and there are other options. But I find this method easy to understand what is going on and a good base to add anything else that you may need to chuck in.
With MVVM, you bind controls in your view to properties and commands in your ViewModel. The Model represents your database.
Validation of user input can be done in several ways. You can restrict textboxes to only accept certain data, you can validate data in property setters etc etc.
I'm no database expert, but I would collect the information in my VM and add a save button somewhere in the view which validates data and writes it to the database. A cancel button could overwrite the VM properties with the (unchanged) values from the model (database).
(edit: what Pete says :)
I think you are confusing ViewModel with database, your view is binded to an object in the ViewModel, when leaving a TextBox, whatever in the TextBox will be assigned to the object of ViewModel, which is still in memory. You will need a save button, MVVM is just a pattern to separate traditional view and code behind for decoupling and easy unit testing. You still need to perform data validation after save button is clicked. For discard user input and revert to previous state, you could either save your ViewModel data before editing, or use Entity Framework to track and manage data changes.

How to avoid update when form entries are not changed

Presently In my application , on click of grid row , i fill the control of the page with the grid row entries. I have a UPDATE button to save the changes . But even if the don't modify any control values and click on Update button , updation will be done with same values. that triggers a entry to log table .
How can I make the form to call the update only when the values of the controls are different than what is being loaded to them when i click grid.
UPDATE :
Application is not using any pattern like MVVM . the structure what is being followed is very slimier to win forms except the UI . For db interaction ADO.net . It was built already when i joined to this project & even I am new to wpf.
Can anyone help me out ?
I think that you need to do some change tracking on the Entities displayed in the grid. Whenever an Update is executed you check the state of the entities and only update those entities where it's needed. Basically you need to intercept at the level of Property Setters to keep track of changes in the entity. think about:
Using a base class that has some functionality for keeping track of the state of an entity. Very simple: a Boolean hasChanged or more "complex" an Enum with Added, Modified and Deleted or something.
Derive other entities from this base class
Work with public properties and private backing fields to intercept property modifications
When property modifications are executed store the information in a Boolean or Enum in the base class
When the update is initiated by the user loop through the entities presented in the Grid and pick those that have changes and send them to the database.
Some helpfull theory about this might be:
Change tracking on businees objects
Using Properties C# programming guide
ADO.NET Self Tracking Entities
I don't know from your question how tightly the coupling is between the user interface and the database (ADO.NET DataTables or so...). The idea presented above requires some "decoupling" of things. But, is a good basis for further functionalities in your application and can give you some ease of work, clear framework, improved maintenance and might increase performance.
I believe the easiest way to do this is to add a handler to controls, that are used to get user input, that will set some boolean property, e.d. RowWasEdited, to true. Then check this property on UPDATE button click event, do neccessary actions, and set it to false.
But I'm sure that there is something more elegant than this.

Saving only fields that have changed in Entity Framework 4

I have a Windows Form with some textboxes and a Save button. When the form loads the textboxes are populated with data from an entity in my model. When the user clicks on the save button the values in each textbox are written back to the entity and then SaveChanges is called to commit the data to the database.
What I'd like to know is what is the best way to check if the form contains changes? If it doesn't contain changes then I needn't call SaveChanges and I can save writing the record back to the database. If it does contain changes and the user hasn't clicked on the Save button I want to get the user's confirmation that the changes don't need to be saved.
I thought maybe I could just update the entity's fields and then check its State property before calling SaveChanges but this fails as updating any field, even with an identical value, causes the entity to be marked as modified.
So, my question is, what is the best way to check that changes have actually been made to the form before calling SaveChanges?
Thanks,
Matt
You can check the entity state. Just save the data from the textboxes to the entity ans see if the EntityState is EntityState.Unchanged.
Details here: http://msdn.microsoft.com/en-us/library/system.data.entitystate.aspx
Actually updating the field even with the same value as the previous one counts as a modified entity and in most cases this is the correct business rule.
What you could do is keep a copy of the original object that was used to fill the form fields and compare it with the current one using an equality comparer. It's not pretty but it gets the job done in particular cases where you cannot count on the object state manager's opinion of modified.

WinForms data binding with a Save button?

How is data binding in C# WinForms supposed to work when you have a Save button? I don't want the data updated until I press Save!
I have two forms (list and detail) backed by a BindingList<T> collection and my custom object from that collection, respectively. I can bind each form to the list or object appropriately. However, any changes made in the detail form are immediately reflected in the list form - I don't want to save the changes and update the details shown in the list until the Save button is pressed.
Is data binding designed to support this? Is there a common pattern for doing so?
Whichever way I look at it, binding doesn't seem to be able to support this scenario. I've considered the following:
Pass a clone of the object to the detail form, but then I have to reconcile the changes on Save - changes may have been made to the copy in the list in the meantime.
Implementing IEditableObject and calling EndEdit on save almost works as I can prevent the list being notified of the changes made until Save is pressed, but if something else causes a refresh the list is updated with the interim data.
I'm currently left with dispensing with data binding in my detail view, and doing it all manually. Which is rather annoying.
Data binding really wasn't designed for this kind of thing, unfortunately.
The best solution we've found here is to edit object clones, then reconcile the changes, as you mentioned. You may want to come up with a custom collection and/or object interface that helps you manage this type of thing.
Even if the cloning method is slightly more work up front, it's going to be wayyyy less complicated and frustrating than using IEditableObject trying to catch all the possible events that update the data. Not only that, it's a more straightforward approach, and you won't end up with spaghetti code.
If you are set on using a binding list, your best bet would be to implement IBindingList to create the functionality that you desire. It may also be possible to pull this off by simply inheriting from BindingList and overriding the appropriate methods to change the binding list's behavior.
http://msdn.microsoft.com/en-us/library/system.componentmodel.ibindinglist.aspx
If you are not set on using a binding list, it is probably best to do the data manipulations manually based off of the control's events.
Best of luck.

Categories